Compare commits

..

865 Commits
v1.2.0 ... v1.5

Author SHA1 Message Date
Michael Zillgith 24b5e28904 Merge remote-tracking branch 'origin/v1.5' into v1.5 12 months ago
Michael Zillgith 2fc6dc32d1 - fixed problem when compiling with dynamically linked mbedtls (LIB61850-458) 12 months ago
Michael Zillgith 09c57e15f4
Update codeql-analysis.yml to action v2 1 year ago
Michael Zillgith 7d4614ad54 - ACSE: fixed out-of-bound read in parseAarqPdu/parseAarePdu functions (#512)(#513)(LIB61850-441)(LIB61850-442) 1 year ago
Michael Zillgith c62287c7c3 - fixed out-of-bound read in parseAarePdu function (LIB61850-442)(#513) 1 year ago
Michael Zillgith a49d0cc78b - GOOSE receiver: added additional length and plausibility checks to fix #509 1 year ago
Michael Zillgith fd820643c5 - fixed memory leak in IedConnection_setLocalAddress (I6LLCV-97) 1 year ago
Michael Zillgith 3bc94bf1bd - fixed potential buffer overflows in MMS client file service handling (LIB61850-449) 1 year ago
Michael Zillgith 3c29e85b00 Merge branch 'v1.5_develop_416' into v1.5 1 year ago
Maxson Ramon dos Anjos Medeiros 193b8bf054 -added function to set the number of outstanding calls-
IedConnection_setMaxOutstandingCalls (LIB61850-433)
1 year ago
Michael Zillgith 0f2443a2fa - IED connection: Fixed memory leak and memory handling problem in function IedConnection_readDataSetValuesAsync (LIB61850-439) 1 year ago
Michael Zillgith 7afa40390b - ACSE: added check for minimum message size (LIB61850-438) 1 year ago
Michael Zillgith a66e07deae - MMS server: fixed - server is sending data set response larger than negotiated MMS PDU size (LIB61850-435) 1 year ago
Michael Zillgith 681d1b0e05 - .NET API: fixed - crash when GetDataSetDirectoryAsync returns error
(LIB61850-434)
1 year ago
Michael Zillgith 249df0176a - fixed potential memory leak when GooseReceiver is immediately stopped after start (I6PLLCV-71) 2 years ago
Michael Zillgith cdd0684ffb - fixed - potential race condition when using IedConnection_installReportHandler and IedConnection_uninstallReportHandler 2 years ago
Michael Zillgith d6c53b1569 - IedServer: fixed crash when client tries to write complete SGCB structure 2 years ago
Michael Zillgith 76e016f59d - IedConnection: fixed potential memory leak in getDataSetHandlerInternal 2 years ago
Michael Zillgith 2823184077 - fixed - null pointer dereference in mmsServer_handleDeleteNamedVariableListRequest when receiving malformed message (LIB61850-430) 2 years ago
Michael Zillgith 5b350102de - fixed compilation problem when MMS_FILE_SERVICE is not set 2 years ago
Michael Zillgith 8c0a75cee9 - Java tools: Support for time stamp Val elements (updated binary) 2 years ago
Michael Zillgith 7442c8da53 Merge branch 'v1.5' of bitbucket.com:mz-automation/libiec61850 into v1.5 2 years ago
Michael Zillgith 41e1ddd308 - Java tools: Support for time stamp Val elements 2 years ago
Michael Zillgith 6f557c490f - removed some warnings in windows HAL code 2 years ago
Michael Zillgith c83bad2531 - updated CHANGELOG and changed version number to 1.5.3 2 years ago
Michael Zillgith aacf853876 - config file parser dynamically allocates linebuffer to allow multithreaded applications (#484) 2 years ago
Michael Zillgith e7c2e37ad4 Merge branch 'v1.5' of bitbucket.com:mz-automation/libiec61850 into v1.5 2 years ago
Michael Zillgith 1072d54f13 - fixed - IEC 61580 server: dataset is not released when RCB.Datset is set to empty string by client (LIB61850-425) 2 years ago
Michael Zillgith 7fee3e5995 - parse time values in model configuration file (LIB61850-426) 2 years ago
Michael Zillgith ec9519a0e7 - PAL: fixed wrong order of function arguments for fread and fwrite functions 2 years ago
Michael Zillgith ab8ac8304d - GOOSE publisher: fixed bug in default parameter handling 2 years ago
Michael Zillgith 5012b3e358 - added GOOSE publisher API documentation to doxygen file 2 years ago
Michael Zillgith ec097240a6 - udpated config file generator binary(2) (LIB61850-418) 2 years ago
Michael Zillgith 1f1b005d26 - config file generator: added missing code for GSEControl (LIB61850-418) 2 years ago
Michael Zillgith f734c450cb - udpated config file generator binary (LIB61850-418) 2 years ago
Michael Zillgith 1d62270730 - Config file generator: support multiple access points for GOOSE and SMV control blocks (LIB61850-418) 2 years ago
Michael Zillgith 27df38d205 - MMS client: parsing of servicecsSupported in MMS init response is off by one (LIB61850-419)(#469) 2 years ago
Michael Zillgith 23928b2b34 - fixed - potential memory leaks in goose publisher code (#464) 2 years ago
Michael Zillgith 37453fd3c1 - some code cleanup 2 years ago
Michael Zillgith 87ba6b0514 - added updated compiled versions of config file and static model generator (LIB61850-67) 2 years ago
Michael Zillgith 4a5a092796 - config file generator/static model generator: added support for SampledValueControl.smpMod (LIB61850-67) 2 years ago
Michael Zillgith 1c1e3766da - config file generator: added code to add SMVCBs to config files (LIB61850-67) 2 years ago
Michael Zillgith e51fda3a06 - IED server: added code to create SMVCBs with the dynamic model API (LIB61850-67) 2 years ago
Michael Zillgith 6f96104a09 - replaced select by poll in linux hal (LIB61850-416)(#463) 2 years ago
Michael Zillgith d0e0dc22e9 - .NET API: Added finalizer to ControlObject (#459) 2 years ago
Michael Zillgith 30fec0a79f - MMS server: added support for write access with component alternate access (LIB61850-414) 2 years ago
Michael Zillgith 684a6ea92e - MMS client: added function MmsConnection_writeVariableComponent to write to variables with alternate component access (LIB61850-414) 2 years ago
Michael Zillgith dce3a9dab4 - fixed - server sends dchg report when only dupd is enabled in RCB (LIB61850-411) 2 years ago
Michael Zillgith d658fe89ab - .NET API: Save TLSConfiguration instance in IedServer to avoid garbage
collection (LIB61850-410)
2 years ago
Michael Zillgith 718b3cda2c - updated doc comment 2 years ago
Michael Zillgith 6cd2eab066 - make write access to RCB elements configurable according to ReportSettings (LIB61850-404) 2 years ago
Michael Zillgith f41667367a - GOOSE subscriber: fixed - possible heap corruption in parseAllData due to missing validity check in bit-string handling (LIB61850-402) 2 years ago
Michael Zillgith f951ebc08e - Added function IedConnection_setLocalAddress to define local IP address and optionally local port of a client connection (LIB61850-378) 2 years ago
Michael Zillgith 8798c739ba - IED server: fixed problem with implicit ResvTms setting when reserved with RptEna (LIB61850-400) 2 years ago
Michael Zillgith 097c055f96 - IED server: fixed - segmentation fault when compiled with CONFIG_MMS_THREADLESS_STACK (LIB61850-398) 2 years ago
Michael Zillgith 48b73261c3 - IED server: added ControlAction_getSynchroCheck and ControlAction_getInterlockCheck functions 3 years ago
Michael Zillgith 79a8eaf260 - added missing checks in iec61850_client_example_control (#442) 3 years ago
Michael Zillgith 76fd58e9be - fixed - MMS server: messages can be corrupted when TCP buffer is full (LIB61850-385) 3 years ago
Michael Zillgith a385a74c4d - fixed - .NET: IedConenction.WriteDataSetValues throws a
NullReferenceException (LIB61850-384)
3 years ago
Michael Zillgith b6867c9c88 - fixed - server send invalid response- when client uses wrong ctlModel (LIB61850-383) (#435) 3 years ago
Michael Zillgith edc1735916
Merge pull request #430 from mbourhis/mbourhis/add-rcb-subscription-example-for-Python-wrapper
Python wrapper: add RCB subscription example
3 years ago
Michael Zillgith 8dae8c1cbe - fixed - IedConnection_setRCBValuesAsync crashes when RCB is already reserved by other client (LIB61850-382) 3 years ago
Mikael Bourhis 5f767ad03e Python wrapper: add RCB subscription example
Signed-off-by: Mikael Bourhis <mikael.bourhis@smile.fr>
3 years ago
Michael Zillgith 9b977e2e4f - updated error handling in IedConnection_getDataSetDirectoryAsync/IedConnection_createDataSetAsync (LIB61850-379) 3 years ago
Michael Zillgith 880d4918f5 - fixed - outstanding call not released in IedConnection_getDataSetDirectoryAsync (LIB61850-379) 3 years ago
Michael Zillgith 68ee9b056a - updated version number to 1.5.2 3 years ago
Michael Zillgith 27340ef5c5 Merge branch 'v1.5_develop_373' into v1.5_develop_merging 3 years ago
Michael Zillgith e11f113b98 - renamed TLSConfiguration_EventLevel to TLSEventLevel 3 years ago
Michael Zillgith 699d75dcd3 - updated required mbedtls version to 2.28.x 3 years ago
Michael Zillgith a657eb7721 - applied coding style 3 years ago
Michael Zillgith c630abb8d1
Merge pull request #415 from mbourhis/add-parameter-for-choosing-MMS-port-in-server-examples
Examples: add command line parameter for choosing the MMS port in som…
3 years ago
Michael Zillgith 19d05f5dc0
Merge pull request #423 from fedefrancescon/fix/iec-62351-messages
Fixing Security events messages to match IEC62351-100-3
3 years ago
Michael Zillgith 6904705083
Merge pull request #422 from fedefrancescon/fix/renegotiation-reset-on-crl-update
CRL checks on socket read/write and ssl cache expire
3 years ago
Michael Zillgith bfd87c703d
Merge pull request #421 from fedepell/tls_reset
tls: add method to reset used CRL (certificate revocation list)
3 years ago
Michael Zillgith 559bc76b34
Merge pull request #420 from fedefrancescon/feature/added-cmake-option
Added few cmake options
3 years ago
Federico Francescon c5979072c9 Added check for changed CRL on socket read/write. Added reset of renegotiation ssl cache on CRL add 3 years ago
Federico Francescon cf02b9fa3a Fixing Security events messages to match IEC62351-100-3 3 years ago
Federico Pellegrin 29a4f498f9 tls: add method to reset used CRL (certificate revocation list)
Add a method to be able to reset the CRL, otherwise any previously
added CRL will stay there until the object is totally destroyed.
This proves to be needed for cases when we need to delete the
CRL (ie. it expired) during the lifetime of the server.
3 years ago
Federico Francescon 28e9e07c7e Added some options to cmake and updated defautls to match base `make` configuration 3 years ago
Michael Zillgith ba18d18c8d - fixed - dynamic model helper functions: Check added to Cancel object for CDC APC 3 years ago
Michael Zillgith ce2ce7e96b
Merge pull request #417 from DavidKorczynski/cifuzz-int
Create cifuzz.yml
3 years ago
Michael Zillgith da088a1938 - replaced all control data access errors with codes allowed in 8-1:2011 table 87 (LIB61850-375) 3 years ago
Michael Zillgith ad0bc86908 - fixed wrong number in TLS event code define (LIB61850_366) 3 years ago
Michael Zillgith b355b64bf1 - .NET API: Added support for TLS event handler (LIB61850-373) 3 years ago
David Korczynski afc2d1035e Create cifuzz.yml 3 years ago
Michael Zillgith b6cd6b61e0 - IED Server: added function to set time quality for internally updated times (LIB61850-372) 3 years ago
Michael Zillgith 23d71f322d - fixed - servers sends object-access-unsupported on GetAllData when ReadAccessHandler is installed (LIB61850-370) 3 years ago
Michael Zillgith df66698b4d - added TLSConnection object to provide more context in TLS event callback (LIB61850-366) 3 years ago
Michael Zillgith 91b0e6ed67 - fixed - endless loop sending reports when MMS PDU size is too small (LIB61850-365) 3 years ago
Mikael Bourhis 9da09a22a9 Examples: add command line parameter for choosing the MMS port in some server examples
Some 'server' examples already have this capability.
Complete the 'server' example list that support the possibility of using
another MMS port than the default one (port '102').

Signed-off-by: Mikael Bourhis <mikael.bourhis@smile.fr>
3 years ago
Michael Zillgith 98f088a1d3 - removed redundant declarations (LIB61850-359) 3 years ago
Michael Zillgith 4b5db538fd
Merge pull request #411 from fedepell/fix_cert_copy
tls: fix order of operations to copy peer certificate
3 years ago
Michael Zillgith 65318c44b6
Merge pull request #410 from fedepell/crl_update_also_from_file
TLS: update CRL load time also when loading from file
3 years ago
Federico Pellegrin e1e6919411 tls: fix order of operations to copy peer certificate
The memcpy is done before assigning the length, so the length is not
set and is therefore either 0 (so no peer certificate will be available)
or a random number (that can lead to crashes) making the feature not work.

The MR simply copies first the length that will make the memcpy work.
3 years ago
Federico Pellegrin 3f8150e391 TLS: update CRL load time also when loading from file
Similarly as done when loading a CRL directly, this allows to
have the CA chain recalculated for ongoing connections also when
using CRLs from files.
3 years ago
Michael Zillgith d00fb7fffb - removed some VC++ warnings 3 years ago
Michael Zillgith 80f609d5e6 Merge branch 'v1.5_feature_339' into v1.5 3 years ago
Michael Zillgith 10622ba36b - fixed path traversal vulnerability in MMS file services (LIB61850-357) 3 years ago
Michael Zillgith dd3e2a6870 - fixed - create multiple integrity reports in the same interval when integrity timeouts are aligned (LIB61850-323) 3 years ago
Michael Zillgith e29736d732 - IED server: added missing call to getNextRoundedStartTime (LIB61850-323) 3 years ago
Michael Zillgith d34b3f4f70 - fixed - server scrahs when SyncIntegrityReportTimes in active and
IntgPd=0 (LIB61850-355)
3 years ago
Michael Zillgith 021b3100ac - fixed some VC++ compiler warnings 3 years ago
Michael Zillgith 893e298107 - fixed - missing API export declarations for functions IedServerConfig_setSyncIntegrityReportTimes and IedServerConfig_getSyncIntegrityReportTimes (LIB61850-353) 3 years ago
Michael Zillgith 219111eef1 - IED server: fixed - possible deadlock when IedServer_lockDataModel is used from multiple threads (LIB61850-352) 3 years ago
Michael Zillgith 7c06680cba - MMS server: fixed - possible deadlock in obtainFile-service/file upload task (LIB61850-351) 3 years ago
Michael Zillgith a3b04b7bc4 - MMS server: fixed potential null pointer dereference when confirmedServiceResponse for fileOpen is received with invoke-id 0 (LIB61850-348) 3 years ago
Michael Zillgith fa8e3c0798 - TLS: added TLS alert callbacks; support for session resumption with session IDs (LIB61850-339) 3 years ago
Michael Zillgith 15398c9ab5 - MMS_SERVER: fixed bug in getNameList request handling when domain ID is too long (LIB61850-346) 3 years ago
Michael Zillgith 1615c8ea9a - added type checks when using asn1c parsing results for whole MmsPdu (LIB61850-343) 3 years ago
Michael Zillgith aeb8cb6157 - MMS client: added function MmsConnection_sendRawData for test purposes 3 years ago
Michael Zillgith 4fb8113821 - fixed wrong check for empty itemId 3 years ago
Michael Zillgith 30217b41cc - GOOSE subscriber: fixed vulnerabilities related to malformed bit-string, integer, and unsigned values (LIB61850-342) 3 years ago
Michael Zillgith 9424917185 - MMS server: fixed bug in handling of continueAfter parameter of getNameList request (LIB61850-341) 3 years ago
Michael Zillgith 22f6a823ea - changed StringUtils_createStringInBuffer function to consider max buffer size (LIB61850-333) 3 years ago
Michael Zillgith 8addfc2095 - replaced most str(n)cpy/str(n)cat calls (LIB61850-333) 3 years ago
Michael Zillgith 4d951e04c5 - encode boolean true value as 0x01 instead of 0xff to avoid interoperability problems 3 years ago
Michael Zillgith 3fe0effcda Merge branch 'v1.5_develop_323' into v1.5_develop 3 years ago
Michael Zillgith 5b4f6f2fd9 - fixed sscanf format string in config_file_parser.c 3 years ago
Michael Zillgith a4fdf089bb - fixed locking mechanism in logging.c (LIB61850-327) 3 years ago
Michael Zillgith b3868a2f9f - removed some cppcheck warnings 3 years ago
Michael Zillgith 319dc4494b - fixed problem: negative presentation layer and ACSE results are ignored by client 3 years ago
Michael Zillgith a9efd32dbc - fixed wrong buffer size in client side report handling 3 years ago
Michael Zillgith 35ac479430 - fixed strncpy usage 3 years ago
Michael Zillgith 00bf70aa8c - fixed memory leak in server read request handling (LIB61850-325) 3 years ago
Michael Zillgith 8fe6f0d551 - fixed memory leak in reuse of client connection (related to socket extension buffer) 3 years ago
Michael Zillgith 7d90a01287
Merge pull request #387 from JamieSlome/v1.5
Create SECURITY.md
3 years ago
Michael Zillgith 9f09152d7c - fixed - TLS: CRL is ignored 3 years ago
Michael Zillgith 03a2137087 Merge branch 'v1.5' of github.com:mz-automation/libiec61850 into v1.5 3 years ago
Michael Zillgith 10a4bc6e76 - fixed memory leak in reuse of client connection (related to socket extension buffer) 3 years ago
Michael Zillgith 25bcd14618 - dynamic code generator: replace invalid characters in generated function names 3 years ago
Jamie Slome d2b36449c2 Create SECURITY.md 3 years ago
Michael Zillgith fd514f32d6 - added IedServerConfig_setSyncIntegrityReportTimes/IedServerConfig_setSyncIntegrityReportTimes wrapper to .NET API (LIB61850-323) 3 years ago
Michael Zillgith cfbe677bc5 - added feature: synchronization of integrity report times (LIB61850-323)
- fixed potential memory access problems in ReportControlBlock getter functions
3 years ago
Michael Zillgith 9032e84415
Merge pull request #383 from vermeulenthi/swig-control-handler-and-python-sync-wrapper
Swig control handler and python sync wrapper
3 years ago
Thibaut Vermeulen 8b43a644b1 python service wrapper: add state management for blocking IO in python 3 years ago
Thibaut Vermeulen 26bec663d2 control server for python: add control action handler for operate server 3 years ago
Michael Zillgith c76b5dd2da - server reporting: added code to prevent race condition with
RCBEventHandler
3 years ago
Michael Zillgith bb7c2421cd - server: added RCBEventHandler event types REPORT_CREATED and OVERFLOW 3 years ago
Michael Zillgith ee948a0c08 - added function ReportControlBlock_getResv 3 years ago
Michael Zillgith 030ae3f7b5 Merge branch 'v1.5_develop' into v1.5 3 years ago
Michael Zillgith e44a44c9e7 - parseNamedVariableAttributes: fixed new code 3 years ago
Michael Zillgith 3288bc0fc5 - MmsConnection_readNamedVariableListDirectory: added code to parse array index and array component of data set entries (LIB61850-317) 3 years ago
Michael Zillgith 584a733b2a - mms_utility: added option to read data set directory 3 years ago
Michael Zillgith b62060b67f - fixed bug creating "Cancel" in CDC_APC_create 3 years ago
Michael Zillgith 5fe49d4618 - fixed wrong MMS protocol version check (#379) 3 years ago
Michael Zillgith 1954da2b78 - .NET API: added IedServer.GetFunctionalConstrainedData method
(LIB61850-317)
3 years ago
Michael Zillgith 532298c378 - RCBEventHandler: replaced GI event by purgeBuf event when client
disables RCB instance (LIB61850-316)
3 years ago
Michael Zillgith 5ca0cd5512 Merge branch 'v1.5_develop' into v1.5 3 years ago
Michael Zillgith d4312d21ac - fixed bugs in ReportControlBlock getter functions and .NET wrapper
code
3 years ago
Michael Zillgith 1213b67a5a Merge branch 'v1.5' of bitbucket.org:mz-automation/libiec61850 into v1.5 3 years ago
Michael Zillgith b444fba88c - added more debug output for linux socket driver 3 years ago
Michael Zillgith bf747f6bea - removed some compiler warnings 3 years ago
Michael Zillgith e51ef87bf5 - fixed compilation problems with C++/VS 3 years ago
Michael Zillgith 19f7066c38 - fixed - SV publisher encoding problem when svID or datset length > 127 bytes (LIB61850-315)(#382) 3 years ago
Michael Zillgith ee2c461ff0 - added const to parameters of StringUtils_startsWith 3 years ago
Michael Zillgith 3cb6123a63 - IedServerConfig: added missing variable initialization 3 years ago
Michael Zillgith 377d708f4e - enabled TLS 1.2 support in mbedtls configuration 3 years ago
Michael Zillgith 3e5fadce4b - fixed - server doesn't respond SBOw when waiting for select callback (LIB61850-313) 3 years ago
Michael Zillgith f60ff65fc4 - improved MmsValue handling; fixed MmsValue(OCTET-STRIG) maximum size problem (LIB61850-150) 3 years ago
Michael Zillgith 9d9f03585f - IED server: improved control state machine performance (LIB61850-312) 4 years ago
Michael Zillgith f0651adb36 - add GOOSE subscriber/Ethernet layer support to listen to specific multicast messages 4 years ago
Michael Zillgith 2adb4dec23 - BSD socket HAL: make server side connection sockets non-blocking (LIB61850-243) 4 years ago
Michael Zillgith 258651eca8 Merge branch 'v1.5_issue_243' into v1.5_develop 4 years ago
Michael Zillgith 210cf30897 - fixed - GOOSE subscriber is not processing octet string when longer than the one received at first time (LIB61850-232) 4 years ago
Michael Zillgith 77e8144348 - removed empty lines 4 years ago
Michael Zillgith d7b48a891e - updated cmake minimum version requirement to 3.5.1 4 years ago
Michael Zillgith cb78c0e403 - updated documentation 4 years ago
Michael Zillgith 398b14e65f - added null pointer protection to some constructors/destructors 4 years ago
Michael Zillgith 8aa988068c - MacOS thread layer: replaced semaphore by mutex 4 years ago
Michael Zillgith d40b359292 - updated windows socket implementation; fixed Socket_checkAsyncConnectState function 4 years ago
Michael Zillgith 1f2da92626 - fixed position range check in MmsValue_getOctetStringOctet 4 years ago
Michael Zillgith ec1678e88a - fixed bug in length calculation for abort PPDU 4 years ago
Michael Zillgith c838255c1e
Merge pull request #367 from cedricboudinet/svsub_getSmpSynch_v1.5
adding SVSubscriber_ASDU_getSmpSynch to v1.5
4 years ago
Michael Zillgith 457b43a6e7 - updated CHANGELOG 4 years ago
Michael Zillgith c210e086cd - .NET API: fix problem with garbage collected delegates for async
client control functions (LIB61850-301)
4 years ago
Michael Zillgith c7b554beb3 - updated static model files for beaglebone demo 4 years ago
Michael Zillgith f7f3c2ae8f - fixed vulnerability of GOOSE subscriber to malformed messages (LIB61850-304) 4 years ago
Michael Zillgith 19c617c4f3 - updated version to 1.5.1 4 years ago
Michael Zillgith cfa94cbf10 - fixed - Bug in presentation layer parser can cause infinite loop (LIB61850-302) 4 years ago
Michael Zillgith 96e93c4be3 - fixed compilation problem with option CONFIG_MMS_THREADLESS_STACK 4 years ago
Michael Zillgith 2092f42f80 - .NET wrapper: fixed problems with garbage collected delegates for async client functions (LIB61850-301) 4 years ago
Michael Zillgith a82964bd66 - fixed - TPKT error when connection is interrupted during message reception (LIB61850-299) 4 years ago
Michael Zillgith 5d1f66d7e6 - .NET API: Fixed bug in IedConnection.GetFileAsync 4 years ago
Michael Zillgith 824c9ad5dd Merge branch 'v1.5_feature_274' into v1.5 4 years ago
Michael Zillgith f98c1a956d - handle presentation layer data messages with transfer-syntax-name 4 years ago
Michael Zillgith 56847ec171 - removed field in ReportControl 4 years ago
Michael Zillgith a7362928f4 - added semaphore for server side RCB value access 4 years ago
Michael Zillgith c3191b2864 - .NET API: added additional properties for Server.ReportControlBlock 4 years ago
Michael Zillgith e06b485258 - ensure RESERVED event before ENABLE event 4 years ago
Michael Zillgith 81b26f1cb6 - added more ReportControlBlock methods 4 years ago
Michael Zillgith b374644d30 - added functions Timestamp_fromMmsValue and Quality_toMmsValue 4 years ago
Michael Zillgith b27681f408 - implemented GET_PARAMETER event for IedServer_RCBEventHandler
- implemented additional access functions for ReportControlBlock to allow access to runtime values
4 years ago
Michael Zillgith d036b09712 - added .NET wrapper for RCBEventHandler 4 years ago
Michael Zillgith 94563cb9f6 - additional methods for ReportControlBlock 4 years ago
Michael Zillgith 83e21e207b - added additional events for IedServer_RCBEventHandler 4 years ago
Michael Zillgith 88148f39ac - added IedServer_RCBEventHandler 4 years ago
Michael Zillgith d5ec52ef78 - mms client: improved locking for outstanding calls 4 years ago
Michael Zillgith 8c55ff636d - made server report reservation compatible with Ed. 2.1 (LIB61850-293) 4 years ago
Michael Zillgith aaf893da34 - fixed - UBRB: library can't work at the same time with URCB with preconfigured client and URCB without preconfigured client (LIB61850-292)(#355) 4 years ago
Michael Zillgith 32087c47de - fix - server crashes when presentation message has no user data (LIB61850-291)(#368) 4 years ago
Cedric Boudinet 20b99b4ef3 adding SVSubscriber_ASDU_getSmpSynch to v1.5 4 years ago
Michael Zillgith 8918a442e0 - removed some warnings in reporting.c 4 years ago
Michael Zillgith 8eeb6f06b3 - MMS server: query log service returns services error instead of reject message when log does not exist (LIB61850-290) 4 years ago
Michael Zillgith de27a6388d - removed some compiler warnings in sqlite log storage driver 4 years ago
Michael Zillgith e0b5ed180f Merge branch 'v1.5_tcp_perf_problem' into v1.5_issue_243 4 years ago
Michael Zillgith 92a3b7668d - .NET API: added MmsValue.SetOctetStringOctet and MmsValue.GetOctetStringOctet
- added positiion paramter validation for MmsValue_setOctetStringOctet
4 years ago
Michael Zillgith 9d4fb692fe
Merge pull request #358 from mbourhis/add-get-set-for-each-OctetString-octet
MmsValue: add 'get' and 'set' for each octet of OctetString
4 years ago
Michael Zillgith 01b1f96590 Merge branch 'v1.5_feature_260' into v1.5 4 years ago
Michael Zillgith 0dc79d4dd8 - .NET API: Added functions for IedConnction - CreateDataSetAsync, DeleteDataSetAsync, GetDataSetDirectoryAsync (LIB61850-260) 4 years ago
Michael Zillgith 36c65bd2e2 - IedConnection: Add function IedConnection_getDataSetDirectoryAsync 4 years ago
Michael Zillgith 7ac0ccc7b6 - ISO server: create new open client connections list when restarting 4 years ago
Michael Zillgith 93d8dfc856 - reporting.c: fixed report entry counter and assert problems
- IED server: disactivate all RCB instances when stopping the server
4 years ago
Mikael Bourhis 7861582621 MmsValue: add 'get' and 'set' for each octet of OctetString 4 years ago
Michael Zillgith 434b9f59b7 - fixed - IED server: crash during invalid control access - FC=CO on invalid layer (LIB61850-282) 4 years ago
Michael Zillgith 50fc97734e - new function IedConnection_setTimeQuality - Added support to set time quality for client generated time stamps (LIB61850-280) 4 years ago
Michael Zillgith 89812fd333 - removed unused variable 4 years ago
Michael Zillgith 394bf4ccba - IED client: added function IedConnection_createDataSetAsync 4 years ago
Michael Zillgith ce9584d122 - IED client: added new function IedConnection_deleteDataSetAsync 4 years ago
Michael Zillgith 09c77afee4 - BSD socket layer: fixed merging problem 4 years ago
Michael Zillgith 9b19e88af7 - fixed - Server: ctlNum and origin(status) are not updated automatically by the
server when APC command is received (LIB61850-277)
4 years ago
Michael Zillgith 856800936f - added missing typecast 4 years ago
Michael Zillgith a02c63b1de - undo merging problem in socket_win32.c 4 years ago
Michael Zillgith 76b4e9ed7b - fixed typo in socket_win32.c 4 years ago
Michael Zillgith 00b42f969d - Updated comments in hal_ethernet.h 4 years ago
Michael Zillgith 2e18175dac Merge branch 'v1.5_feature_261' into v1.5 4 years ago
Michael Zillgith ce13002ce1 - added const qualifiers to API functions (#348) 4 years ago
Michael Zillgith d49c159686 - updated README 4 years ago
Michael Zillgith 472e586a14 - IedConnection_getLogicalDeviceVariablesAsync: fixed wrong parameter
order when calling MMS layer
4 years ago
Michael Zillgith d7a55eca08 - MMS server: fixed problem with continue-after in some get-name-list handling cases 4 years ago
Michael Zillgith ae6941f451 - fixed - IedConnection: outstanding call on IEC layer is not release under some circumstances (LIB61850-270, LIB61850-251) 4 years ago
Michael Zillgith 6998b7397c Merge branch 'v1.5' of bitbucket.org:mz-automation/libiec61850 into v1.5 4 years ago
Michael Zillgith 6f376620d3 - fixed bug in IsoServer that caused memory violation when the server was restarted while a client was connected 4 years ago
Michael Zillgith c621840d42 - IED client: added missing err initilization in function ControlObjectClient_selectAsync 4 years ago
Michael Zillgith dabff06fe8 - Linux socket layer: ignore EINTR signal during poll function 4 years ago
Michael Zillgith 7c3601cb74 - IED client: send RptEna as first element when RCB is to be disabled 4 years ago
Michael Zillgith 6b9437b8c0 - unified HAL with lib60870 and libtase2 (LIB61850-261) 4 years ago
Michael Zillgith 82e57900fa - .NET API: added wrapper for IedConnection_setFile and IedConnection_setFilestoreBasepath (LIB61850-258) 4 years ago
Michael Zillgith 9790630d25 - updated .NET core 2.0 library project to .NET standard 2.0 4 years ago
Michael Zillgith 263c34f016 Merge branch 'v1.5' of github.com:mz-automation/libiec61850 into v1.5 4 years ago
Michael Zillgith f259096e12 - fixed problem with double free of TLS configuration structure (LIB61850-254) 4 years ago
Michael Zillgith e67cb1af31 Merge branch 'v1.5_tcp_perf_problem' of bitbucket.org:mz-automation/libiec61850 into v1.5_tcp_perf_problem 4 years ago
Michael Zillgith db5e24bc1a - fixed memory leak in socket extension buffer
- increased size of socket extension buffer
4 years ago
Michael Zillgith ba45973d59 Merge branch 'v1.5' into v1.5_tcp_perf_problem 4 years ago
Michael Zillgith f0c1d6348e - removed debug output 4 years ago
Michael Zillgith 6525a72930 - fixed TCP performance problem for Linux (LIB61850-243) 4 years ago
Michael Zillgith c5579758bb - IED server: improved accuracy of integrity report intervals 4 years ago
Michael Zillgith bb64d9d8fe - .NET API: GooseSubscriber - added GetGoId, GetGoCbRef, GetFataSet
methods
- .NET API: GooseReceiver - store references to all added
GooseSubscribers to prevent garbage collection
- update documentation comments for GooseSubscriber API
4 years ago
Michael Zillgith 2ace50b712 - .NET API: Fixed problem with AccessViolationException in
GooseControlBlock.GetDstAddress
4 years ago
Michael Zillgith ca58c70342 - MMS server: fixed data race bug in transmitBuffer handling (#338) 4 years ago
Michael Zillgith 4ffed8de11 - IED server: fixed crash when IEDName+LDInst is too long 4 years ago
Michael Zillgith 982b1097fc - .NET API: fixed bug - server write access handler causes
"CallbackOnCollectedDelegate" exception (LIB61850-236)
4 years ago
Michael Zillgith 161e88a3ef - MMS server: fixed potential crash when client connection closed during file upload (LIB61850-2)
- MMS client: fixed problem - doesn't close file when the setFile (obtainFile) service is interrupted e.g. due to connection loss (LIB61850-230)
4 years ago
Michael Zillgith 8bec67d8d6
Create codeql-analysis.yml 4 years ago
Michael Zillgith 78cd0ed391 - IedServer: fixed bug - in executeControlTask MmsMapping* is used instead of ControlObject* for ControlAction parameter of checkHandler (#333) 4 years ago
Michael Zillgith 40b8f99201 - Ethernet Socket (Windows): fixed bug and added workaround for problem
on Windows (most GOOSE/SV messages are not received when waiting with
WaitForMultipleObjects - observed with winpcap 4.1.3 and Windows 10
4 years ago
Michael Zillgith ef1895c2be - fixed problem in BER integer decoder (problem with GOOSE fixed length message decoding) 4 years ago
Michael Zillgith da08489bc3 - .NET API: Fixed memory release problem in method
ModelNode.GetObjectReference
4 years ago
Michael Zillgith 7185c3b8d4 - IED server: add support for SMV control blocks ("SMVC") in config file
parser
4 years ago
Michael Zillgith de3aba0cb6 - .NET API: added support for server integrated GOOSE publisher
- IED server: fixed bug in GoCBEventHandler
4 years ago
Michael Zillgith c8078e3eb1 - fixed problem in BSD ethernet layer (#328)
- fixed bug in cmake file for BSD
4 years ago
Michael Zillgith 1bb76893a2 - fixed compilation problem when compiling without GOOSE support (#325) 4 years ago
Michael Zillgith 8b82cd34e1 - IedConnection: fixed problem - outstanding calls not released in function deleteFileAndSetFileHandler (#322) 4 years ago
Michael Zillgith 1a09b9548a - IED server: control handling - fixed problem in test flag handling 4 years ago
Michael Zillgith 3514e08252 - Linux Ethernet: fixed uninitialized memory 4 years ago
Michael Zillgith 8578344e85 - GOOSE subscriber: restore old behavior when data set array is provided by user 4 years ago
Michael Zillgith 1b2d194694 - IED server: For SBOes check test flag match when accepting operate (sSBOes8) 4 years ago
Michael Zillgith d1fd0c7e34 Merge branch 'v1.5' of https://github.com/mz-automation/libiec61850 into v1.5 4 years ago
Michael Zillgith f866132e84 - IED server: Reject Cancel/SBOw in WaitForChange state - fixed problem with test case sCtl26 4 years ago
Michael Zillgith efe4513d11 - .NET API: fully implemented dispose pattern in DataSet class 4 years ago
Michael Zillgith b2f417bdbf - updated comments and readme 4 years ago
Michael Zillgith fcefc746fe - updated CHANGELOG 4 years ago
Michael Zillgith 91bb816621 - updated macos semaphore handling
- updated CHANGELOG
4 years ago
Michael Zillgith 72feb2f614 - updated Makefiles to compile code for latest version of MacOs 4 years ago
Michael Zillgith 9e6e3487da - removed compiler warnings 4 years ago
Michael Zillgith e0b4a720dd - added/updated comments in SV publisher example 4 years ago
Michael Zillgith cb3f460fcf - .NET API: added functions to access DataAttribute properties 4 years ago
Michael Zillgith 530cdc0383 - .NET API: added function IedModel.GetDeviceByInst 4 years ago
Michael Zillgith f6110c1158 - updated API documentation for command termination handler 4 years ago
Michael Zillgith 5aec4c94b1 - added tool support for transient data objects (genmodel/genconfig) 4 years ago
Michael Zillgith 7540b6a8d7 - Fixed problem with installed headers - application code does not compile only with installed headers 4 years ago
Michael Zillgith abd26eedca - IED client: fixed memory leak when reusing IedConnection 4 years ago
Michael Zillgith cda2eba93b - .NET API: added LogControlBlock and SettingGroupControlBlock classed
to added LCBs and setting groups to server data model
4 years ago
Michael Zillgith ee9d6656b3 - .NET API: Added GSEControlBlock class to add GoCBs to server data
model
4 years ago
Michael Zillgith 56bda24641 - .NET API: Added method ReportControlBlock.SetPreconfiguredClient 4 years ago
Michael Zillgith 5ba428fa5b - .NET API: MmsValue - added functions to create empty visible string and set visible string value
- .NET API: DataAttribute - save data attribute type
4 years ago
Michael Zillgith 3532623319 - IED server: Goose publisher - set NdsCom when data set not configured or GoEna fails because of large data set 4 years ago
Michael Zillgith c4dcd37449 - added new function DataAttribute_setValue 5 years ago
Michael Zillgith 2b1104c0d3 - IED server - control model - send AddCause with operate- for DOes, SBOes control models 5 years ago
Michael Zillgith bd4bd0fab6 - IED server: GoCB has invalid data set reference when datSet="" in SCL file 5 years ago
Michael Zillgith 4e15343f5b - IED server: integrated GOOSE publisher - lock data model during GOOSE retransmission to avoid corrupted GOOSE data 5 years ago
Michael Zillgith f49be0d844 - added server example for dead band handling 5 years ago
Michael Zillgith ea268b46a7 - IED server: make presence of RCB.Owner configurable at runtime with function IedServerConfig_enableOwnerForRCB (B1502/S1634) 5 years ago
Michael Zillgith fd3847dcc5 - IED server: make presence of BRCB.ResvTms configurable at runtime with function IedServerConfig_enableResvTmsForBRCB (F1558) 5 years ago
Michael Zillgith d546ebac6f - restrict maximum recursion depth in BerDecoder_decodeLength when indefinite length encoding is used to avoid stack overflow when receiving malformed messages 5 years ago
Michael Zillgith ed810fde0f - MmsValue_equalTypes: check parameters for NULL to avoid dereferencing NULL pointer 5 years ago
Michael Zillgith e04e424b02 - fixed oss-fuzz issues 31399, 31340, 31341, 31344, 31346 5 years ago
Michael Zillgith 7f381b54ba - fixed bug in oss-fuzz adaptor 5 years ago
davkor 0fd1176ede Change tabs to spaces. 5 years ago
davkor 91f3ed7989 Added fuzzer for oss-fuzz integration. 5 years ago
Michael Zillgith dc22dc76ec - IED server: fixed bug in log service - old-entry and old-entry-time not updated 5 years ago
Michael Zillgith 42bb617841 - HAL: implemented Hal_setTimeInNs for windows 5 years ago
Michael Zillgith d5d8b70dc2 - .NET API: Added additional ModelNode methods. Added additional method IedServer.HandleWriteAccessForComplexAttribute. Fixed some problems with WriteAccessHandler. 5 years ago
Michael Zillgith 842bc271cd - IED server: added new function IedServer_handleWriteAccessForComplexAttribute. Changed WriteAccessHandler behavior when ACCESS_POLICY_ALLOW. 5 years ago
Michael Zillgith cc905b5013 - IED server/model: Added additional functions for ModelNode access 5 years ago
Michael Zillgith 9e27ed5a77 - MMS server: add compile time configuration options to enable/disable fileDelete and fileRename services (fileRename is now disabled by default) 5 years ago
Michael Zillgith 5512b0f9be
Merge pull request #309 from mbourhis/mbourhis/python_swig_event_handler_for_command_termination
Mbourhis/python swig event handler for command termination
5 years ago
Michael Zillgith 4dc971ba56 - MMS server: better data model lock handling for performance improvements 5 years ago
Michael Zillgith 60d66e5ba4 - some code beautification 5 years ago
Michael Zillgith 3984a47324 - Linux - Ethernet: replace IFF_PROMISC by IFF_ALLMULTI 5 years ago
Michael Zillgith 5afa1310f3 - IED server: Add function ModelNode_getObjectReferenceEx 5 years ago
Michael Zillgith 5e39c94cf3 - IED server: allow IedServer_setServerIdentity with some parameters set to NULL 5 years ago
Michael Zillgith cdd00da057 - .NET API: Added IDisposable interface to IedServer and IedModel classes
- .NET API: Added method IedModel.SetIedName
5 years ago
Mikael Bourhis e47601a81e Python wrapper: about the wrapped callbacks, maintain a 'map' of subscribers
The 'callback' function is a part of the 'Subscriber' class.
Once the 'event' (or asynchronous message) is received, the 'Subscriber' object
forwards the data to the 'Handler' object.
With this approach, the 'event' processing algorithm can be defined
in a Python subclass by the user.

Each 'subscriber' class has a function that matches the C function pointer.
But this function is a static method, shared with all instances of the class.
In order to dispatch the message/data to the right instance,
we maintain a dictionary of instantiated objects.

Therfore, we have added the following internal services :
 * bool registerNewSubscriber(EventSubscriber*, id);
 * EventSubscriber* findSubscriber(id);
 * void unregisterSubscriber(id);
5 years ago
Mikael Bourhis b1fc481ab8 Python wrapper: add some quality improvements 5 years ago
Mikael Bourhis da9b77af7a Python wrapper: add handler class for the reception of CommandTermination events 5 years ago
Michael Zillgith 35713550fb - updated windows socket code (should fix #301) 5 years ago
Michael Zillgith fe39cc9b24 - IED server: control models - fixed bug that only one control is unselected when connection closes 5 years ago
Michael Zillgith 19f2cbf0e7 - CMake build: add new configuration option CONFIG_USE_EXTERNAL_MBEDTLS_DYNLIB to allow build using externally built mbedtls DLL/shared object 5 years ago
Michael Zillgith b0fb3259e5 - IedConnection/common: fixed new bug in code to separate elements of object reference 5 years ago
Michael Zillgith 4f0667b597 - removed some warnings and code cleanup 5 years ago
Michael Zillgith de2ce1d008 - removed some compiler warnings (when compiling with clang) 5 years ago
Michael Zillgith db1671587e - IED server: fixed bug - logs (journals) are added to all logical devices instead of just the parents 5 years ago
Michael Zillgith 9e064ab709 - IED Server: prevent integrated GOOSE publisher to crash when ethernet socket cannot be created 5 years ago
Michael Zillgith 23a3b3a371 - IED server: make compatible with tissue 1178 5 years ago
Michael Zillgith 5630275a0d - make file-tool example more robust 5 years ago
Michael Zillgith 8111734f40 Merge branch 'v1.5' of https://github.com/mz-automation/libiec61850 into v1.5 5 years ago
Michael Zillgith 6c2b9ad473 - IED server: reporting - implemented behavior according to tissue 1432 5 years ago
mbourhis 69bf867c41
Mbourhis/python wrapper add missing include to extend python api (#291)
* Python wrapper: add an 'include' directive to have access to the 'mms_type'

* Python wrapper: add an 'include' directive to include the ConfigFileParser API
5 years ago
Michael Zillgith 895e74d680 - updated cmake files to use only C++ when compiling with VS (new examples) 5 years ago
Michael Zillgith db0a7d5e8a - updated cmake files to use only C++ when compiling with VS 5 years ago
Michael Zillgith 74a227bdf2 - IED server: WriteAccessHandler can tell the stack not to update the
value when returning DATA_ACCESS_ERROR_SUCCESS_NO_UPDATE
5 years ago
Michael Zillgith 5f2e14f712 Merge branch 'v1.5' of https://github.com/mz-automation/libiec61850 into v1.5 5 years ago
Michael Zillgith 945fe080f3 - removed some compiler warnings 5 years ago
Michael Zillgith 176de25ca0 - IEC 61850 client: IedConnection - list of client control objects is protected by a lock 5 years ago
Michael Zillgith bc29a0b048 - IEC 61850 client: avoid double free when operate and select-with-value on APC fails 5 years ago
Michael Zillgith d08f5a67ac - IED server: fixed problem with client connection handling of setting groups 5 years ago
Michael Zillgith 96ba766a0a - socket-linux: fixed problem in UdpSocket_receiveFrom 5 years ago
Michael Zillgith 8bf76601ea - socket-linux: get source IP address in UdpSocket_receiveFrom 5 years ago
Michael Zillgith 474a482766 IED server: fixed problem with CONFIG_IEC61850_RCB_ALLOW_ONLY_PRECONFIGURED_CLIENT configuration option enabled 5 years ago
Cédric Boudinet bf27774a86 Svsub latency (#288)
* Changing svReceiverLoop to reduce latency

* adding EthernetHandleSet_destroy to svReceiverLoop
5 years ago
Michael Zillgith 40f8b76ad7 - IED server: handle BRCB.Owner correctly when client uses pre-assigned RCB instance 5 years ago
Michael Zillgith 4793e298ff - IED server: fixed problem that BL FC is not writable (#287) 5 years ago
Michael Zillgith ae4f940753 - .NET API: Added support for SelectStateChangedHandler
- .NET API: Added ModelNode.GetObjectReference
5 years ago
Michael Zillgith 0879ad0d46 - HAL: added missing include (sys/select) in serial HAL implementation for linux (#279) 5 years ago
Michael Zillgith c02e99a022 - IEC 61850 client: fixed dead lock in IedConnection_getFileAsync when fileRead times out (#285) 5 years ago
Michael Zillgith 3e98fdfa90 - Client: fixed - IedConnection_getRCBValues doesn't check type of server response (#283) 5 years ago
Michael Zillgith 4deca9a4c0 - IED server: fixed potential deadlock in report module when service tracking is enabled 5 years ago
Michael Zillgith 5d704b8026 - GOOSE subscriber: fixed message validity check 5 years ago
Michael Zillgith a606848a8b - GOOSE subscriber: changed maximum GoID size according to tissue 770 (129 bytes) 5 years ago
Michael Zillgith 7b671f3a01 - GOOSE subscriber: accept GOOSE messages with the correct maximum size of DatSet and GoID 5 years ago
Michael Zillgith b88c4216c8 - IED server: send AddCause for invalid origin also in case of direct control models 5 years ago
Michael Zillgith 1f174c3f65 Merge branch 'v1.5' of https://github.com/mz-automation/libiec61850 into v1.5 5 years ago
Michael Zillgith 8ac9a732df - added function GooseSubscriber_getParserError 5 years ago
Michael Zillgith 2baeb59e61 - added Hal_getTimeInNs function for windows 5 years ago
Michael Zillgith 146dbb9057 - GOOSE subscriber: improved code to detect invalid GOOSE messages 5 years ago
Michael Zillgith 0c9d1b16f8 - fixed struct initialization problem with Visual Studio 5 years ago
Michael Zillgith 8a55ef47bf - IED server: ControlPerformCheckHandler has same parameters when called again in state WAITING_FOR_SELECT 5 years ago
Michael Zillgith 14f4f1ccf0 - IED server: added ControlSelectStateChangedHandler callback for control model 5 years ago
Michael Zillgith fb5ed11001 - IED server: also respect user provided error and addCause from ControlPerformCheckHandler when the handler is called multiple times in waiting-for-select state 5 years ago
Michael Zillgith a5bcd3c251 - IED server: fixed problem - control not unselected after connection is closed for sboClass "operate-many" 5 years ago
Michael Zillgith 9348683462 - IED server: fixed bug in cdc.c (wrong type for tOpOk data attribute) 5 years ago
Michael Zillgith cc80bffa69 - IED server: support for configuration of EditSG service and online visibility of SGCB.ResvTms at runtime 5 years ago
Michael Zillgith 53d8a2f715 - IED server: changed types TrkOps and OptFlds to variable length bit strings 5 years ago
Michael Zillgith 23da9ba28e - IED server: control service tracking - fixed problem with missing attributes for SBOw tracking 5 years ago
Michael Zillgith 981c2dd5f3 - fix problem: TLS does not work with HandleSet 5 years ago
Michael Zillgith e59aa5521e - fixed memory leak in ISO server 5 years ago
Michael Zillgith 767bc887de - IED server: fixed problems in control service tracking 5 years ago
Michael Zillgith 49cc901263 - fixed problem in control service tracking 5 years ago
Michael Zillgith a165d1698d - MMS: changed handling of variable sized bit strings (now also accepts bit strings of larger size, ignoring the bits that exceed the specified size) 5 years ago
Michael Zillgith 3f42387ed7 - IED server: fixed dupd trigger handling 5 years ago
Michael Zillgith e4fcb923a0 - fixed problems in control service tracking 5 years ago
Michael Zillgith 00a821e67e Merge branch 'v1.5' of https://github.com/mz-automation/libiec61850 into v1.5 5 years ago
Michael Zillgith 543d7802f5 - MMS client: add handling of initiate error PDU 5 years ago
Michael Zillgith b27e363372 - IED server: add support for correct CBB handling (required for test case sAss4) and initiate error PDU 5 years ago
Michael Zillgith 18833799cc - updated changelog 5 years ago
Michael Zillgith 42802db6f1 - added -Wextra to Makefile and changed code to avoid resulting warnings 5 years ago
Michael Zillgith 036f60e4f1 - fixed compiler warning 5 years ago
Michael Zillgith 07525b598f Merge branch 'v1.5' of https://github.com/mz-automation/libiec61850 into v1.5 5 years ago
Michael Zillgith 1f56110d32 - removed some compiler warnings 5 years ago
Michael Zillgith 98e7c5816a - code formatting; compiler warnings 5 years ago
Michael Zillgith fb9fc7b88b
Merge pull request #265 from mbourhis/v1.5-fix_GooseEthernetInterfaceId_allocation
IED Server/Goose: Fix the 'Goose Ethernet Interface Id' allocation
5 years ago
Michael Zillgith 7ee278cead - IEC 61850 client: using poll/select to reduce CPU consumption 5 years ago
Mikael Bourhis a095c16139 IED Server/Goose: Fix the 'Goose Ethernet Interface Id' allocation
Issue:
In the case of 'GooseInterfaceId' initialization for all GOOSE
publishers (API function: IedServer_setGooseInterfaceId()), only the pointer of
the character string is saved and used for the next operations.
If the corresponding memory is cleared or overwritten in the
application program, a segfault may occurred in libiec61850.

Proof:
In the 'server_example_goose.c' example, if we used a temporary
allocated memory to store the 'ethernetIfcId', the bug will occur:

        /* set GOOSE interface for all GOOSE publishers (GCBs) */
    +   unsigned int ethernet_interface_id_length = strnlen(ethernetIfcID, 32);
    +   char * tmp_ethernet_interface_id = calloc(sizeof(char), ethernet_interface_id_length + 1);
    +   memcpy(tmp_ethernet_interface_id, ethernetIfcID, ethernet_interface_id_length);
    +
        IedServer_setGooseInterfaceId(iedServer, tmp_ethernet_interface_id);
    +
    +   explicit_bzero(tmp_ethernet_interface_id, ethernet_interface_id_length);
    +   free(tmp_ethernet_interface_id);

(This issue was discovered during the rewriting of 'server_example_goose'
in Python, with the Swig wrapper: the allocated memory for
'ethernetIfcID' parameter in the Swig wrapper is automatically reused)

Fix:
The 'gooseInterfaceId' attribute of 'MmsMapping' in libiec61850 must be a new
allocated memory (with the use of 'StringUtils_copyString()') and deallocated
in the 'MmsMapping_destroy()' function.
5 years ago
Michael Zillgith ec5ccb62a0 - IED server: RCB and LCB service tracking replaced $ with . characters in object references 5 years ago
Michael Zillgith 5e520f21b5 - IED server: added missing data set update in GoCB service tracking object 5 years ago
Michael Zillgith 7e1c2ef18f - IED server: added GoCB event callback
- IED server: added configuration option to use GoCB block handling without the integrated GOOSE publisher (IedServerConfig_useIntegratedGoosePublisher)
5 years ago
Michael Zillgith e1ab323c1b - IED server: added code for log service tracking 5 years ago
Michael Zillgith 3a2eea3611 - extended service tracking example for GoCB and SGCB service tracking 5 years ago
Michael Zillgith fcdb83bc2f - IED server: fixed memory leak in service tracking code
- IED server: fixed bug in GoCB service tracking (goID and dataSet not set)
5 years ago
Michael Zillgith b04e651623
Merge pull request #262 from mbourhis/v1.5-smile-ecs
V1.5 smile ecs
5 years ago
Michael Zillgith bef1ad21b4 - Java Tools: Add support to handle Services.ReportSettings@owner attribute 5 years ago
Michael Zillgith bafe27a0e8 - IED server: add support for tissue 807 (owner attribute in RCB is only present when ReportSettings@owner attribute is true) 5 years ago
Michael Zillgith 9809582f96 - IED server: implemented tissue 1453 also for writing to "RptId"
(purgeBuf only executed when value changes)
5 years ago
Michael Zillgith 42013e1550 - MMS client: fixed bug in TLS connection handling 5 years ago
Michael Zillgith 0b58716ea3 - IED server: fixed issue - read access to SGCB is not possible when read access handler is installed 5 years ago
Michael Zillgith 3e1a23a6d0 Merge branch 'v1.5' of https://github.com/mz-automation/libiec61850 into v1.5 5 years ago
Michael Zillgith aabe20031f - GOOSE subscriber: always copy GoID and DatSet from GOOSE message; always create new MmsValue instance for GOOSE data set when subscriber is observer 5 years ago
Michael Zillgith 69e359b03f - added new DataAttributeType value IEC61850_TYPE_UNKNOWN 5 years ago
Michael Zillgith a17e9603e0 - config file parser: fixed problem when compiling with visual
studio/C++
5 years ago
Michael Zillgith 2bc47a6a6c - IED server: added configuration file support for data set entries with array elements or array element components 5 years ago
Michael Zillgith 131fcf5236 * IEC 61850 client: added missing check in ClientReportControlBlock_getConfRev 5 years ago
Michael Zillgith ed8c8b3ac7 - IEC 61850 server: fixed some variable initialization issues caused by recent changes 5 years ago
Michael Zillgith e4b2849894 - fixed problems in handling array elements and array element components 5 years ago
Michael Zillgith 6a3c66eafa - fixed bug in MmsConnection_readMultipleVariables: send invaid messsage and memory access errors when too many items are passed to the function exhausting MMS payload size 5 years ago
Michael Zillgith ee4da06690 - IEC 61850 server: fixed problem with test case sRp4 - RCB RptID attribute is not empty after writing empty string 5 years ago
Michael Zillgith cbd5c0b36f - GOOSE/SV publisher: remove internal header file from API header 5 years ago
Michael Zillgith 504c260667 - fixed program crash when normal mode parameers are missing in presentation layer (#252) 5 years ago
Michael Zillgith 9ab37e9836 - IED Server/GOOSE: Don't send GOOSE message with new event while data model is locked 5 years ago
Michael Zillgith 805d73b86f - GOOSE: added GOOSE observer feature (GooseSubscriber listening to all GOOSE messages) and GOOSE observer example 5 years ago
Michael Zillgith 9ac8192bae - IED Server: fixed service tracking object references for RCB and GoCB service tracking 5 years ago
Michael Zillgith 3e83cd6194 - GOOSE receiver: improvements in GOOSE receiver 5 years ago
Michael Zillgith 34647c6876 - GOOSE publisher: Added doxygen comments and functions GoosePublisher_publishAndDump, GoosePublisher_setStNum, GoosePublisher_setSqNum 5 years ago
Mikael Bourhis 401a436c95 Python wrapper: move the 'event handler' classes into a subdirectory 5 years ago
Michael Zillgith 473eec8464 - GOOSE/SV publisher: remove internal header file from API header
(cherry picked from commit 46d6769a89)
[Romain: Apply the patch to v1.5]
Signed-off-by: Romain Naour <romain.naour@smile.fr>
5 years ago
Mikael Bourhis f5b5c0d3ad Python wrapper: add the support of the 'Goose publishing' 5 years ago
Romain Naour dcbd9f94ab examples/server_example_basic_io
There is an access error while using iec61850_client_example1 with server_example_basic_io.

From [1]:
    /* write a variable to the server */
    value = MmsValue_newVisibleString("libiec61850.com");
    IedConnection_writeObject(con, &error, "simpleIOGenericIO/GGIO1.NamPlt.vendor", IEC61850_FC_DC, value);

The error code is IED_ERROR_ACCESS_DENIED = 21.

By default access to variables with FC=DC and FC=CF is not allowed, fix this
by changing the access policy as suggested by [2].

[1] https://github.com/mz-automation/libiec61850/blob/v1.4.2.1/examples/iec61850_client_example1/client_example1.c#L71
[2] https://libiec61850.com/libiec61850/documentation/iec-61850-client-tutorial/#comment-61994

Signed-off-by: Romain Naour <romain.naour@smile.fr>
5 years ago
Mikael Bourhis 172883478a Python wrapper: declare all the C 'char *buffer' output parameters as a Python output string of 1024 max size
Needed for example for:
  - MmsValue_printToBuffer(values, buffer, buffer_size);
5 years ago
Mikael Bourhis 30f98e54cb Python wrapper: add handler class for the reception of GOOSE events 5 years ago
Mikael Bourhis ca97f2548f Python wrapper: add handler class for the reception of ReportControlBlock events 5 years ago
Mikael Bourhis 7bac935648 Python wrapper: add generic classes for handling events (like ReportControlBlock or GOOSE) 5 years ago
Mikael Bourhis 7c68e3e3f6 Python wrapper: add the support of the 'Goose subscription'
The callback for the processing of the received GOOSE is still missing for now.
5 years ago
Mikael Bourhis c2c7c7171e Python wrapper: add 'user-defined data types' for Timestamp (msSinceEpoch, nsSinceEpoch) 5 years ago
Michael Zillgith 649db2b3d6 - IEC 61850 server: extended control service tracking
- IEC 61850 server: partially implemented setting group service tracking
- IEC 61850 server: partially implemented GoCB service tracking
5 years ago
Michael Zillgith b857e4c4ec
Merge pull request #246 from RomainNaour/v1.5-client_example_reporting
iec61850_client_example_reporting: revert changes from MMS server pot…
5 years ago
Michael Zillgith 88acbd49c4 - COTP: fixed possible heap buffer overflow when handling message with invalid (zero) value in length field (#250) 5 years ago
Michael Zillgith 0129032f08 - IEC 61850 server: fixed - cancel command for time activated control returns object-access-denied even in case of success 5 years ago
Michael Zillgith cc22c69fb1 Merge branch 'v1.5' of https://github.com/mz-automation/libiec61850 into v1.5 5 years ago
Michael Zillgith 24a380c845 - IEC 61850 server: added updating of missing attributes for control
service tracking
5 years ago
Michael Zillgith 8bc7b75e11 - IEC 61850 server: fixed crash in control service tracking when application doesn't register control handler 5 years ago
Michael Zillgith 2467457b5b - IEC 61850 server: fixed problem with wrong service-type for service
tracking when writing URCBs (SetBRCBValues instead of SetURCBValues)
5 years ago
Michael Zillgith 80d11fbf78 - IEC 61850 server: started to implement control service tracking
(implemented support for SpcTrk)
5 years ago
Michael Zillgith 4ee5891388 - fixed debug output in iso_server.c 5 years ago
Michael Zillgith 2f5817e0ac - IEC 61850 server: implemented service tracking for BRCBs and URCBs 5 years ago
Michael Zillgith 920eabe31f - IEC 61850 client: ReasonForInclusion type is now int to be compatible
with C++
5 years ago
Romain Naour 1c2db6e3be iec61850_client_example_reporting: revert changes from MMS server potential crash fix
The commit 0d4930ac25 renamed the RCB values
from "testmodelSENSORS/LLN0.RP.events01" to "simpleIOGenericIO/LLN0.RP.EventsRCB01"
with other changes.

But since "testmodelSENSORS" doesn't exist on the server_example_basic_io
the program fail with:

Reading data set directory failed!
failed to read dataset
getRCBValues service error!

Revert all testmodelSENSORS related changes with the previous code.
Now we get the two report as expected:

received report for simpleIOGenericIO/LLN0.RP.EventsRCB with rptId Events1
  report contains timestamp (1596190789): Fri Jul 31 12:19:49 2020
  simpleIOGenericIO/GGIO1.SPCSO1.stVal[ST] (included for reason 16): false
  simpleIOGenericIO/GGIO1.SPCSO2.stVal[ST] (included for reason 16): false
  simpleIOGenericIO/GGIO1.SPCSO3.stVal[ST] (included for reason 16): false
  simpleIOGenericIO/GGIO1.SPCSO4.stVal[ST] (included for reason 16): false

received report for simpleIOGenericIO/LLN0.RP.EventsRCB with rptId Events1
  report contains timestamp (1596190790): Fri Jul 31 12:19:50 2020
  simpleIOGenericIO/GGIO1.SPCSO1.stVal[ST] (included for reason 16): false
  simpleIOGenericIO/GGIO1.SPCSO2.stVal[ST] (included for reason 16): false
  simpleIOGenericIO/GGIO1.SPCSO3.stVal[ST] (included for reason 16): false
  simpleIOGenericIO/GGIO1.SPCSO4.stVal[ST] (included for reason 16): false

Signed-off-by: Romain Naour <romain.naour@smile.fr>
5 years ago
Michael Zillgith 004789cf39 - fixed error in API documentation 5 years ago
Michael Zillgith 4a3702112e - MMS client: fixed potential problem in multi-variable write response parsing 5 years ago
Michael Zillgith 27ae0a5c0f - removed outdated comment 5 years ago
Michael Zillgith 69d93f398c - IEC 61850 client: fixed bug - IedConnection_setRCBValuesAsync always return 0 instead of invoke-ID 5 years ago
Michael Zillgith de6886c6f3 - MMS: fixed problem in handling of indefinite length encoded BER elements 5 years ago
Michael Zillgith cf7dbcc612 - HAL: added thread/semaphore support for MacOS 5 years ago
Michael Zillgith 02f03aea2f - GOOSE subscriber: added optional destination address check for GOOSE messages 5 years ago
Michael Zillgith 7ece9922ed - BSD socket: added support for async client socket functions 5 years ago
Michael Zillgith 092d8786ac - IEC 61850 server: control model - fixed bug in handling of check flags 5 years ago
Michael Zillgith 538b9698bc - COTP: fixed bug in sendBuffer loop 5 years ago
Michael Zillgith c4de14eb45 - MmsValue: fixed unaligned memory access problems for MMS_FLOAT variables 5 years ago
Michael Zillgith d38e590c99 - IEC 61850/MMS server: control - allow WaitForExecutionHandler to trigger LastApplError message 5 years ago
Michael Zillgith 5f02ea1661 - IEC 61850 server: control module return AddCause command-already-in-execution when second operate is received while command is executed 5 years ago
Michael Zillgith ede2c7766c
Merge pull request #239 from RomainNaour/v1.5-musl
V1.5 musl
5 years ago
Romain Naour 801d43e118 serial_port_linux: Add missing include sys/time.h
POSIX says `struct timeval` is defined if <sys/time.h> is included.

Adding this header allow to build against musl-libc.

Signed-off-by: Romain Naour <romain.naour@smile.fr>
(cherry picked from v1.4 branch commit 661405eb60)
5 years ago
Romain Naour a7d744d55d use <poll.h> instead of <sys/poll.h>
The manpage of poll(2) states that the prototype of poll is defined
in <poll.h>. Use that header file instead of <sys/poll.h> to allow
compilation against musl-libc.

Signed-off-by: Romain Naour <romain.naour@smile.fr>
(cherry picked from v1.4 branch commit 4cad505fc9)
5 years ago
Michael Zillgith d85b7ac777 - IEC 61850 client: reporting - support data set entries with multiple reasons for inclusion 5 years ago
Michael Zillgith b3c5ecdcf2 - IEC 61850 server: report service - combine quality and value change of a FCDO in the same report when model is locked (send data set entry with multiple reason-for-inclusion) 5 years ago
Michael Zillgith 3bf0e9a689 - MMS client: fixed potential problem in handling of next invoke ID 5 years ago
Michael Zillgith 9ca6d696c3 - MMS client: added additional check when parsing read response 5 years ago
Michael Zillgith 83e8e14603 - .NET API: fixed bug in DataSet destructor 5 years ago
Michael Zillgith 9b5c45a0b3 - added hal_base.h to installed headers in Makefile 5 years ago
Michael Zillgith db5740db0e - updated java tools binaries 5 years ago
Michael Zillgith 0e184389b9 - Java tools: moved minTime, maxTime from GSEControl to GSE; updated
GOOSE server example CID file
5 years ago
Michael Zillgith b6b94b0438 - fixed VS compilation problems 5 years ago
Michael Zillgith e1eb09d55b - MmsValue: added NULL checks for all memory allocations
- MmsValue: buffer for float/double data is now part of the MmsValue structure and not allocated separately
5 years ago
Michael Zillgith 9c2942a261 - integrate HAL functions in iec61850.dll 5 years ago
Michael Zillgith ae66945751 - file-tool: open file in binary mode (to fix problem with file download on windows) 5 years ago
Michael Zillgith 1fcbad0b65 - .NET API: added ControlAction.SetError method 5 years ago
Michael Zillgith d55afdfb92 - IEC 61850 server: added support to listen on multiple IP addresses and ports (new function IedServer_addAccessPoint) 5 years ago
Michael Zillgith 12d703e453 - IEC 61850 server: Added ControlAction_setError function - with this function the user application can control the error code used in LastApplError and CommandTermination messages 5 years ago
Michael Zillgith 94dcbb0119 - removed unused variable 5 years ago
Michael Zillgith b0fbf9f3a3 - IEC 61850 server: fixed - Configuration option CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS = -1 doesn't work (#231) 5 years ago
Michael Zillgith d42f96ee97 - IEC 61850 server: fixed - control model - peer connection is not always available when control handlers are called (#232) 5 years ago
Michael Zillgith 7e4e396403 - updated server_example_control 5 years ago
Michael Zillgith a6bad96d25 - fixed examples that have control handlers with old signature 5 years ago
Michael Zillgith 0bc014580a - linux/windows socket: close socket when connect fails in Socket_connectAsync 5 years ago
Michael Zillgith 8e95e7dbb8 - MMS: also update bitstring value when source bit string is of smaller size than the bitstring to be updated 5 years ago
Michael Zillgith c4a5fd2f27 - IEC 61850 client: fixed memory leak in async select function 5 years ago
Michael Zillgith b0bce92073 - updated CHANGELOG 5 years ago
Michael Zillgith 73f1a98b4a Merge branch 'v1.4' into v1.5 5 years ago
Michael Zillgith 994eea4b9a - GOOSE subscriber: fixed crash when GOOSE messages misses time stamp 5 years ago
Michael Zillgith cdf371e92e - fixed: MmsValue_printToBuffer fails with empty MMS_OCTET_STRING (#227) 5 years ago
Michael Zillgith cc88bea491
Create greetings.yml 5 years ago
Michael Zillgith cc08420e50 - IEC 61850 server: fixed problem with logging when log data set contains FCDO (#225) 5 years ago
Michael Zillgith 97e65d5743 - fixed problem encoding OID with arc values 0 5 years ago
Michael Zillgith d798814fb4 - updated CHANGELOG 5 years ago
Michael Zillgith 1744616866 - IEC 61850 server: RCB - fixed problem that other client can "steal" reservation 5 years ago
Michael Zillgith 4871989658 - MMS client: fixed bug in log entry parsing (#224) 5 years ago
Michael Zillgith 95f751ef63 - IEC 61850 server: fixed potential null pointer dereference in multi
thread mode when server is stopped
5 years ago
Michael Zillgith 6a2db3fe46 - IEC 61850 server: fixed bug in single threaded mode (windows) 5 years ago
Michael Zillgith 4a15e9987b - IEC 61850 server: fixed compilation error in single thread mode 5 years ago
Michael Zillgith fa3c5dd256 - updated CHANGELOG 5 years ago
Michael Zillgith f4957cf62a - IEC 61850 server: wait for background thread termination before data model is released 5 years ago
Michael Zillgith 0d4930ac25 - MMS server: fixed potential crash when get-named-variable-list-attributes response doesn't fit in MMS PDU. Server returns service error in this case 5 years ago
Michael Zillgith 9526b6aece - updated CHANGELOG 5 years ago
andy1547 efe889d567
Add value property to quality .NET (#217)
- Added ushort quality  property.

Co-authored-by: Andrew Moorcroft <andrew.moorcroft@nortechonline.co.uk>
6 years ago
andy1547 ff53028ec4
Added various dotnet methods required for server configuration (#216)
- Added the ability to set/read URCB buffer size in dotnet.
-  Added IedServer_getNumberOfOpenConnections, ClientConnection_getLocalAddress and server identity methods for dotnet.
Co-authored-by: Andrew Moorcroft <andrew.moorcroft@nortechonline.co.uk>
6 years ago
Michael Zillgith 29efa333f8 - IEC 61850 server: allow server to start without logical devices in data model (#218) 6 years ago
Michael Zillgith cb8f159914 - IEC 61850 server: unbuffered reporting - send first integrity report after integrity timeout (before it was sent when the RCB was enabled) 6 years ago
Michael Zillgith fd84d21c10 - IEC 61850 client: fixed bug in ClientReportControlBlock - some allowed structures for RCB were rejected 6 years ago
Michael Zillgith bfcb65eabc - add 64 bit integer support to MmsValue_printToBuffer 6 years ago
Michael Zillgith c7f7989b85 - IEC 61850 server: control - unselect when operate with wrong origin parameters, check if check parameter matches for SBO 6 years ago
Michael Zillgith 0ba4a70d33 - IEC 61850 server: fixed missing report timestamp update for unbuffered reporting 6 years ago
Michael Zillgith bfef9ce5e9 - .NET API: added IedServer:setServerIdentity method 6 years ago
Michael Zillgith 09b23aaa74 - IEC 618580 server: Added function IedServer_setServerIdentity to set values for MMS identity service 6 years ago
Michael Zillgith ae07c77d39 - CDC helpers: added functions to create ISC and BAC CDCs 6 years ago
Michael Zillgith 2dba040c1a - CDC helper functions: added stSeld and attributes from ControlTestingCDC to control CDCs 6 years ago
Michael Zillgith 922f3055b4 - updated cmake files to work with cmake 2.8 6 years ago
Michael Zillgith 800c76c50e - update cmake files 6 years ago
Michael Zillgith 3fd4fed886 - .NET API: fixed memory management issue in MmsValue.SetElement (see #213) 6 years ago
Michael Zillgith 4aaced2639 - IEC 61850 server: unselect control when oper is not accepted
- IEC 61850 server: send select-failed for control when origin parameter is not valid
6 years ago
Michael Zillgith 4dede9b8a1 - updated version number to 1.4.2 6 years ago
Michael Zillgith d8153483b5 - IEC 61850 server: fixed control handling to comply with test case sCtl25 6 years ago
Michael Zillgith 3a248a4f20 - IEC 61850 server: fixed control handling to comply with test case sCtl11 6 years ago
Michael Zillgith 0c83507727 - IEC 61850 server: pass origin, ctlNum, ctlVal to select handler for SBOw 6 years ago
Michael Zillgith 7d22aba900 - removed internal header files from install target (#214) 6 years ago
Michael Zillgith 85506b994d Merge pull request #211 from andy1547/feature/add-iedserver-set-attribute-methods
Added SetBoolean and SetInt32 methods for dotnet.
6 years ago
Michael Zillgith 0a51f2688d Merge pull request #208 from andy1547/feature/iedserver-config-dotnet
Added FileServiceEnabled and LogServiceEnabled settings for dotnet
6 years ago
Michael Zillgith ca43b02095
Merge pull request #211 from andy1547/feature/add-iedserver-set-attribute-methods
Added SetBoolean and SetInt32 methods for dotnet.
6 years ago
Michael Zillgith 757dd4240d
Merge pull request #208 from andy1547/feature/iedserver-config-dotnet
Added FileServiceEnabled and LogServiceEnabled settings for dotnet
6 years ago
Michael Zillgith 8726bb19d1 Merge branch 'v1.5' of https://github.com/mz-automation/libiec61850 into v1.5 6 years ago
andy1547 94bcd9e2e2 Added missing CDC creation methods for dotnet (#201)
* Added enumerated status CDC creation method for dotnet.
* Added APC and SPC CDC creation methods for dotnet.
* Fixed typo in method name.
* Added BCR CDC creation method for dotnet.
* Added ENC creation method for dotnet.
* Added remaining missing CDC creation methods for dotnet.
6 years ago
andy1547 0e71091830
Added missing CDC creation methods for dotnet (#201)
* Added enumerated status CDC creation method for dotnet.
* Added APC and SPC CDC creation methods for dotnet.
* Fixed typo in method name.
* Added BCR CDC creation method for dotnet.
* Added ENC creation method for dotnet.
* Added remaining missing CDC creation methods for dotnet.
6 years ago
Michael Zillgith 0be1a98d51 - added UDP socket support to windows socket layer 6 years ago
Andrew Moorcroft e954529117 Added SetBoolean and SetInt32 methods for dotnet. 6 years ago
Michael Zillgith e2d3ef2c72 Merge branch 'v1.5' of https://github.com/mz-automation/libiec61850 into v1.5 6 years ago
Michael Zillgith 4bbfd43f2e - added UDP support to socket layer 6 years ago
Michael Zillgith ac008c2e76 - SV publisher/subscriber: add support for timestamps with nanosecond resolution 6 years ago
Michael Zillgith 33db13de16 - Timestamp: added functions to handle times with ns resolution 6 years ago
Michael Zillgith d0da45be41 - HAL: added new functions to handle system time with nanosecond resolution 6 years ago
Andrew Moorcroft d984573067 Added FileServiceEnabled and LogServiceEnabled settings to dotnet IED Server Configuration. 6 years ago
Michael Zillgith b4b74c69a4 - windows socket layer: fixed bug - cannot reuse handleset 6 years ago
Michael Zillgith 37d43fe8d4 - windows socket layer: fixed bug - cannot reuse handleset 6 years ago
Michael Zillgith d20da7c15d - TLS: fixed memory leak when TLS authentication fails 6 years ago
Michael Zillgith c71015f240 - TLS: fixed memory leak when TLS authentication fails 6 years ago
Michael Zillgith 1831be663e - updated version to 1.5.0 6 years ago
Michael Zillgith d86055173d - IEC 61850 server: control models - allow delaying select response with check handler (new handler return value CONTROL_WAITING_FOR_SELECT) 6 years ago
Michael Zillgith abcf93416f - added function IedServer_getNumberOfOpenConnections
- IEC 61850/MMS server: refactored connection handling
6 years ago
Michael Zillgith e834bd0cf6 - fixed BSD compilation issues 6 years ago
Michael Zillgith f788256247 - Socket layer: Added function HandleSet_removeSocket
- Socket layer (Linux/BSD): replaced select by poll
6 years ago
Michael Zillgith df0e7c08df - IEC 61850 server: fixed new memory leak in unbuffered reporting 6 years ago
Michael Zillgith b82a78db46 - fixed bug in windows socket layer 6 years ago
Michael Zillgith 8991954e3c - removed header dependencies from API headers 6 years ago
Michael Zillgith 18c2e30f87 - IEC 61850 server: refactored reporting module; unbuffered reports are stored to report buffer and sent by connection handling thread 6 years ago
Michael Zillgith 0237c9b95c - updated CHANGELOG/version number to 1.4.1 6 years ago
Michael Zillgith 925c19bff6 - IED Server: added support for transient data objects 6 years ago
Michael Zillgith 9f86812002 - .NET API: added MmsValue methods BitStringToUInt32BigEndian and BitStringFromUInt32BigEndian 6 years ago
Michael Zillgith afe9afafc0 - MMS get name list service: fixed wrong return value in case of unknown argument for continueAfter 6 years ago
Michael Zillgith d6bf4047e1 - fixed compilation problem when CONFIG_MMS_THREADLESS_STACK is defined 6 years ago
Michael Zillgith 7cff085bf0 Merge branch 'v1.4' of https://github.com/mz-automation/libiec61850 into v1.4 6 years ago
Michael Zillgith b4c7cefb15 - MMS value parser: added plausibility check for bit-string padding value (#200) 6 years ago
Michael Zillgith c23a698c8d - fixed memory leak in windows socket layer (socket connect) 6 years ago
Michael Zillgith 118a731b36 - SV publisher: fixed memory leaks (#191) 6 years ago
Michael Zillgith 7d1a552cde - GOOSE publisher: fixed problem with overflow of stNum and sqNum (see #199) 6 years ago
Michael Zillgith 88fce24b83 - string_utilities.c: added checks if memory allocation fails 6 years ago
Michael Zillgith 320f41fc1f - check return value of getNumberOfElements in MmsValue_decodeMmsData 6 years ago
Michael Zillgith 23e381fa76 - added additional length checks in MmsValue_decodeMmsData to fix #194 6 years ago
Michael Zillgith 6c53924c05 - added additional length check in BerDecoder_decodeLength and checked return values in callers (fix problem #196) 6 years ago
Michael Zillgith 8c1b75b382 - code cleanup; fixed issues from compiler warnings 6 years ago
Michael Zillgith 6cbadb4b45 - IED server: added new function ControlAction_isSelect 6 years ago
Michael Zillgith 2dbd775fe1 - removed "entryId" from unbuffered RCB configuration in some CID/ICD files 6 years ago
Michael Zillgith 881ebac3dc - .NET API: added ControlAction.GetControlTime methods 6 years ago
Michael Zillgith 5fbb67c44c - some code beautification 6 years ago
Michael Zillgith 6738215c8f
Merge pull request #183 from kiraly533/v1.4
TimeActivatedControl before wait check and fixes for file-upload issues.
6 years ago
Michael Zillgith 9192e5d21b .NET: fixed problem in ReportControlBlock.SetRCBValues (see #184) 6 years ago
Michael Zillgith 1120a76ecd - added bool define for older visual studio 6 years ago
Michael Zillgith 5bd03b0611 - IED server: added function ConfigFileParser_createModelFromConfigFileEx with filename as argument to avoid dependency on FileSystem_... functions
- .NET projects: changed target framework of some project files to v4.0
6 years ago
Michael Zillgith cee97f7676 MMS server: handle file close with unknown FRSM ID 6 years ago
Michael Zillgith 11d1a5ca6d fixed problem in time conversion for mingw 6 years ago
Király Péter 3b32c14870 - MMS server: in case of file upload timeout the task will end with proper error response. 6 years ago
Király Péter a03f57c0a7 Merge remote-tracking branch 'mz/v1.4' into v1.4 6 years ago
Király Péter c988b78e5f - MMS server: fixed file upload error with multi-threaded server, added some NULL checks to file-handling. 6 years ago
Michael Zillgith 16c7124c2b - add define to compile with MVC2010 6 years ago
Michael Zillgith 3a820f3546 - improved error handling in iec61850_client_example1 6 years ago
Michael Zillgith b6d8dfc69c - fixed error handling in iec61850_client_example_reporting 6 years ago
Király Péter 7ed8516344 Added getter for the time of the timeActivated controls. 6 years ago
Király Péter a39397d21d Add check call before starting a timeactivated operate, so operates can be denied before the waiting state 6 years ago
Michael Zillgith 8b6e4b0b29
Merge pull request #182 from kiraly533/v1.4
- MMS server: fixed possible crash when client disconnects during fil…
6 years ago
Király Péter c223b1c2b5 - MMS server: fixed possible crash when client disconnects during file upload 6 years ago
Michael Zillgith 17205ed874 - Client: response timeout for connection setup now configurable (default timeout now 5 s instead of 1 s )
- removed configuration option CONFIG_TCP_READ_TIMEOUT_MS
6 years ago
Michael Zillgith aad53f380e - Linux server socket: default backlog is 2 6 years ago
Michael Zillgith 8bbc905533 - IEC 61850 client: improved error handling and fixed potential memory leak in IedConnection_getDeviceModelFromServer 6 years ago
Michael Zillgith 69729bd8a0 - fixed - misspelled function name #180 6 years ago
Michael Zillgith 939476e52a Merge branch 'v1.4' of https://github.com/mz-automation/libiec61850 into v1.4 6 years ago
Michael Zillgith eaaaa2b0a5 Merge branch 'v1.4' of https://github.com/mz-automation/libiec61850 into v1.4 6 years ago
Michael Zillgith 547d5118e0 -replaced timegm implementation on windows. Fixes bug with MMS file times 6 years ago
Michael Zillgith 5e16971bbf - updated documentation 6 years ago
Michael Zillgith 6f7df75d85 - updated README 6 years ago
Michael Zillgith ec947b234e - updated CHANGELOG 6 years ago
Michael Zillgith 6e9047916c - fixed bug in BerInteger_setUint16 6 years ago
Michael Zillgith e4c3875e3e IEC 61850 server: added function ControlAction_getCtlNum to access ctlNum value inside control handlers 6 years ago
Michael Zillgith 83f9f1eaa6 - mms_utility: fixed memory leak 6 years ago
Michael Zillgith 31e183d357 - IEC 61850 client: added additional error code to provide diagnostic information when data set cannot be created because of a non existing data set element 6 years ago
Michael Zillgith 3242f147be - cmake script: excluded mms_utitlity from build on windows 6 years ago
Michael Zillgith 903abe0b6d - MMS client: fixed problem with obtain file timeout with large files 6 years ago
Michael Zillgith 320f511d33 - IEC 61850 client: Added functions IedConnection_setRequestTimeout and IedConnection_getRequestTimeout to C API and IedConnection.RequestTimeout property to .NET API 6 years ago
Michael Zillgith d06ab546a9 - SV subscriber: improved error handling when Ethernet access doesn't work; fixed potential memory leak 6 years ago
Michael Zillgith ebb0f761d2 - GOOSE subscriber example: added error handling when ethernet cannot be accessed 6 years ago
Michael Zillgith 9a97519815 - GOOSE publisher: integrated error handling when Ethernet interface is not available 6 years ago
Michael Zillgith 1549367eed - updated code to use mbedtls-2.16 (LTS version) 6 years ago
Michael Zillgith e7ece50f08 - updated documentation for MMS octet string type (MMS_OCTET_STRING) handling functions 6 years ago
Michael Zillgith cba8bf5714 MMS server: fixed memory access problem when client unexpectedly closed connection during file upload (set-file) 6 years ago
Michael Zillgith 236a773365 - updated java tools 6 years ago
Michael Zillgith c7d0f88ce2 static model generator: Initialize Dbpos value from Val element in ICD/CID file (see github #163) 6 years ago
Michael Zillgith 9c58a886c5 - Linux ethernet driver: don't exit application when interface is not existing 6 years ago
Michael Zillgith 119b3d71f7 Merge branch 'v1.4' of https://github.com/mz-automation/libiec61850 into v1.4 6 years ago
Michael Zillgith ee3d4f0164 - added function GooseReceiver_getInterfaceId
- GOOSE receiver: fixed problem with running state detection after receiver start
6 years ago
Michael Zillgith 4254af3ff9 IEC 61850 client: ControlObjectClient_getLastError provides access to data access error information of last control action 6 years ago
Michael Zillgith dfaae6662d - add .NET support for new PSelector type - pSelector is now a byte array in the .NET API 6 years ago
Michael Zillgith 241ab5a33d linux socket: TCP_USER_TIMEOUT only defined for kernel version 2.6.37+ 6 years ago
Michael Zillgith 6b2404e80b - GOOSE: option to enable/disable VLAN tagging
- IED Server: Allow setting different interfaces for different GOOSE publishers
6 years ago
Michael Zillgith 46d7f6ff2d - SV publisher: make VLAN tagging optional 6 years ago
Michael Zillgith 3391f4c139 Merge branch 'v1.4' of https://github.com/mz-automation/libiec61850 into v1.4 6 years ago
Michael Zillgith 74d78d0618 updated server substitution example 6 years ago
Michael Zillgith cbd0008f48 - IEC 61850 client: fixed - file transfer doesn't release outstanding connection 6 years ago
Michael Zillgith 88849e1663 - added new type PSelector to represent presentation layer selector more flexible 6 years ago
Michael Zillgith 70ec56a0b2 - linux socket: set retransmission timeout to 10 s 6 years ago
Michael Zillgith 2cf288fbeb Merge branch 'v1.4' of https://github.com/mz-automation/libiec61850 into v1.4 6 years ago
Michael Zillgith 57f6df3c3a - HAL(Socket): Added function Socket_getLocalAddress
- IEC 61850 server: Added function ClientConnection_getLocalAddress
6 years ago
Michael Zillgith 2bfd0fd0ef - GOOSE receiver: add support for operation without Ethernet HAL implementation 6 years ago
Michael Zillgith 0b181ae22c - .NET: added missing ignore paramter for test case 6 years ago
Michael Zillgith 01ea43e95f - fixed object reference string buffer size in iec61850_client_example2[2] 6 years ago
Michael Zillgith 486c46229f - fixed object reference string buffer size in iec61850_client_example2 6 years ago
Michael Zillgith 0d025800b4 - added setting of MMS request timeout to .NET 6 years ago
Michael Zillgith 965cebbe2d - added export definitions to MmsVariableSpecification functions 6 years ago
Michael Zillgith f34cdb24e7 - add define to export symbols when building DLL 6 years ago
Michael Zillgith 84fcfbbd22 - MMS client/server: handle missing invoke ID in reject/error PDUs 6 years ago
Michael Zillgith 4c123c0c3c - MMS server: fixed potential deadlock in multi-thread mode 6 years ago
Michael Zillgith 834291e7c7 - .NET API: added new function MmsValue.NewUtcTime 6 years ago
Michael Zillgith 73417cdbf2 - Added additional check in MmsVariableSpecification_getChildValue 6 years ago
Michael Zillgith b909907041 - updated java binaries 6 years ago
Michael Zillgith bac41913c1 - Java SCL parser: Val element content for times is interpreted as UTC times 6 years ago
Michael Zillgith d4304e0a38 - IEC 61850 server: URCB will not release reservation (and owner) when RCB is disabled 6 years ago
Michael Zillgith 4f59099c59 Merge branch 'v1.4' of https://github.com/mz-automation/libiec61850 into v1.4 6 years ago
Michael Zillgith 0d5fa50947 - MMS client: added missing socket release when connection was not opened 6 years ago
Michael Zillgith 60741394a3 - MMS server: fixed bug in obtain file service (crash when target directory doesn't exist) 6 years ago
Michael Zillgith 8f5b501d75 - removed inline function declarations 6 years ago
Michael Zillgith f5236f84fc - IEC 61850 client: convert MMS error for outstanding call limit to IedClientError 6 years ago
Michael Zillgith 4b4a85dcc2 Merge branch 'v1.4' of https://github.com/mz-automation/libiec61850 into v1.4 6 years ago
Michael Zillgith 2e9761c541 - IED server: cancel outstanding control tasks when client closes connection (to prevent blocking the connection for waiting time activated controls) 6 years ago
Michael Zillgith c2d73c3fe8 - fixed bug parsing OID string with space as separator 6 years ago
Michael Zillgith 7cb69c983a - additionally allow comma and space as separators in ap-titles used in API functions 6 years ago
Michael Zillgith daff495246 - MMS client/server: accept empty bit strings 6 years ago
Michael Zillgith 8099734f11 - .NET API: adopted to new server side control API 6 years ago
Michael Zillgith 6c14425ca8 - IEC 61850 server: refactored control model API (changed handler signatures, added ControlAction object to access origin and set addCause value, ...)
- IEC 61850 client: added ControlObjectClient_getLastError function
6 years ago
Michael Zillgith 5a3c3ba4b3 - fixed client_example_reporting.c 6 years ago
Michael Zillgith 28e2acbd33 - IED server: avoid dynamic memory allocation in control module 6 years ago
Michael Zillgith f0df571f42 - IED server: made code compatible with C++ 6 years ago
Michael Zillgith a9fa07a7d4 - IED server: some memory optimizations in control module 6 years ago
Michael Zillgith 544b301861 - .NET API: added missing native function declarations 6 years ago
Michael Zillgith 2911781070 - IEC 61850 server/reporting: fixed bug when checking for invalid data set member 6 years ago
Michael Zillgith 38d67a4e69 - IEC 61850 server/reporting: send access error "object-value-invalid"
when data attribute in report data set has no value
6 years ago
Michael Zillgith ebc71d9731 - IEC 61850 common: moved some internal code to better seperate
client/server side code
6 years ago
Michael Zillgith 16c061b4df - MMS server API: removed dependency from internal header file iso_server.h 6 years ago
Michael Zillgith 5a83af9206 - moved mms_server.h back to public API (see github #117) 7 years ago
Michael Zillgith 6e9a794047 - examples: changed SCL file extensions to reflect the correct file type 7 years ago
Michael Zillgith d376370aaa - IEC 61850 server: control model - implemented automatic handling of opRcvd, opOk, and tOpOk when present in data object 7 years ago
Michael Zillgith a3c2c4652e - IEC 61850 server: control model - implemented automatic handling of stSeld when present in data object 7 years ago
Michael Zillgith c98a2b0baa - MMS server: fixed connection handling problem in multi-threaded mode 7 years ago
Michael Zillgith 95cf87ebb4 - added missing Java files 7 years ago
Michael Zillgith 994484d1a6 - MMS server: added semaphore for open connections map to prevent problem in multi-threaded mode 7 years ago
Michael Zillgith ecdbb8fcff Merge branch 'v1.4' of https://github.com/mz-automation/libiec61850 into v1.4 7 years ago
Michael Zillgith 1f144a008e - fixed memory leak in ClientSVControlBlock_create 7 years ago
Michael Zillgith 26a45a078b - added error handling code to client_example_log.c
- fixed bug in ClientSVControlBlock
7 years ago
Michael Zillgith 9f03b5d3b8 - fixed client_example_async to compile on Windows 7 years ago
Michael Zillgith 0cddcb7d12 - MMS client: changed signature of MmsConnection_FileReadHandler 7 years ago
Michael Zillgith 8ffbd9f265 - removed function MmsValue_deleteIfNotNull (now MmsValue_delete does check for NULL) 7 years ago
Michael Zillgith ac14a4722d - integrated cmake file changes from v1.3 branch 7 years ago
Michael Zillgith 0d2775742a - IEC 61850 client: fixed problems in ClientReportControlBlock_create (see github #134) 7 years ago
Michael Zillgith 93d8bfb19d - updated CHANGELOG file 7 years ago
Michael Zillgith 0308f87b85 - SV subscriber: fixed bug in function SVReceiver_enableDestAddrCheck 7 years ago
Michael Zillgith 9f8d52005b - MMS client: fixed problem when reusing connection 7 years ago
Michael Zillgith f2c811c7c7 - IedServer: fixed potential deadlock when IedServer_stop is directly called after IedServer_start 7 years ago
Michael Zillgith 287769dcba - IEC 61850 client: handle reason code correctly when report contains data with different reason code (see github #133) 7 years ago
Michael Zillgith b35a566145 - IEC 61850 server: fixed problem in report module 7 years ago
Michael Zillgith 0dff4286aa - merged latest changes to the server reporting module from 1.3 branch
- merged with 1.3 branch
7 years ago
Michael Zillgith 0421ea2101 - fixed bug in windows socket abstraction 7 years ago
Michael Zillgith 9ed1510223 - added function StringUtils_convertIPv6AdddressStringToByteArray 7 years ago
Michael Zillgith 732ad79070 - fixed problem with read access to GCB (see github #130) 7 years ago
Michael Zillgith 0b2d97c738 - COTP: added payload length validation (see github #127) 7 years ago
Michael Zillgith 9959158995 - make: fixed dynamic library name for win64 (see github #129) 7 years ago
Michael Zillgith b6be355a99
Merge pull request #118 from stv0g/fix-invalid-datasize-calculation
sv-publisher: fix invalid calculation of the total packet length
7 years ago
Michael Zillgith e51b676414
Merge pull request #120 from stv0g/add-missing-bsd-hal
Add stubs for missing functions in BSD HAL
7 years ago
Steffen Vogel 5aa78a8b18 sv-publisher: simplify calculation of length of BER length field 7 years ago
Steffen Vogel 88b74cfab8 hal: add stubs for missing functions in BSD (closes #113) 7 years ago
Steffen Vogel a81b76c5e3 sv-publisher: fix invalid calculation of the total packet length in case the payload is larger than 127 bytes 7 years ago
Michael Zillgith 9309cb78de - added missing definition 7 years ago
Michael Zillgith 199d091c6d - IEC 61850 server: don't send bufOvfl for unbuffered reports (see #101) 7 years ago
Michael Zillgith 0a27ec758f - IED server: handling thread mode changed 7 years ago
Michael Zillgith 952f12bffb - mms-utility: added read array 7 years ago
Michael Zillgith 452abd7dbf - MMS client/server: added support for component alternate access for generic variable read requests 7 years ago
Michael Zillgith 6af7973b09 - IsoClientConnection_associateAsync: added check if socket creation has been successful 7 years ago
Michael Zillgith 46f87a1656 - fixed client TCP keep alive problem (see #115) 7 years ago
Michael Zillgith 3d8ab44a49 - MMS client: improved handling of malformed messages when reading data
- MMS client: improved handling of malformed messages when receiving reports
- MMS client: fixed potential memory leak when receiving malformed messages
7 years ago
Michael Zillgith 1c461009c2 - MMS client/server: fixed potential memory leaks in TLS handling code 7 years ago
Michael Zillgith 87cac8dc00 - code formated 7 years ago
Michael Zillgith 4bd8b40b6c - code formatting 7 years ago
Michael Zillgith 01933c415a - fixed cmake install target (#102) 7 years ago
Michael Zillgith 1434f3e345 Merge branch 'v1.4' of https://github.com/mz-automation/libiec61850 into v1.4 7 years ago
Michael Zillgith d9cb36817a - IEC 61850 server: fixed problem with wrong purge buffer invocation when using dynamic data set in buffered report control block 7 years ago
Michael Zillgith 4f1dd17752
Merge pull request #93 from aaribaud/v1.4-python3-bindings-fix
Fixed Python 3 bindings support
7 years ago
Davide Andreuzza 832bb5e9f1 fix bufOvfl typo in parsing OptionFields 7 years ago
Albert ARIBAUD 92c3d3adb8 Fixed Python 3 bindings support
1. Allow specifying Python interpreter version with BUILD_PYTHON_VERSION

2. Fix Python modules install path generation (would produce spurious
   line feed which would cause destination directory to be
   /usr/lib/python*/dist-packages\n -- note the final \n!
7 years ago
Michael Zillgith 256f55aaef - .NET API: added more async client functions 7 years ago
Michael Zillgith 821b065453 - .NET API: added more async functions (control, association, data set, get variable specification) 7 years ago
Michael Zillgith b4eab23c12 - updated swig configuration for python 7 years ago
Michael Zillgith 9826749400 - resolved compilation issues with visual studio 2017 7 years ago
Michael Zillgith 5e35e6694b - added new example folder 7 years ago
Michael Zillgith b6c9a56d4a - .NET API: added more async functions
- .NET API: added GetFileDirectoryEx function
. file-tool: add "s" option to send only a single get file directory request
7 years ago
Michael Zillgith e252715aa9 - added report subscription activation to non-thread mode client example 7 years ago
Michael Zillgith 4157c9c5da - extended server_example_control to show how to change ctlModel with online service 7 years ago
Michael Zillgith bbb56a16a3 - removed some compiler warnings 7 years ago
Michael Zillgith 3b577fbf3a - file-tool: added option to show sub directory content 7 years ago
Michael Zillgith 1d61afaa8b - C library: removed C++ style line comments 7 years ago
Michael Zillgith 6a7266da93 - SV publisher/subscriber: improved error handling when configuration is wrong 7 years ago
Michael Zillgith 0c006f2892 - improved error handling in iec61850_9_2_LE_example 7 years ago
Michael Zillgith afab66cb4d - error handling in SV publisher example 7 years ago
Michael Zillgith cd50bc63b2 - fixed install target of Makefile 7 years ago
Michael Zillgith 388337a60d - IEC 61850 client: added support for non-thread mode (IedConnection_createEx, IedConnection_tick)
- added example for non-thread mode client and asynchronous API
7 years ago
Michael Zillgith 5ed474a44a - MMS client: fixed problem with async connect timeout 7 years ago
Michael Zillgith ef076efe9f - IEC 61850 client: fixed problem with connection state handling 7 years ago
Michael Zillgith 3e30910319 - IEC 61850 client: added missing async functions for files 7 years ago
Michael Zillgith 0842097b7e - IEC 61850 server: fixed some small bugs and compiler warnings
- IEC 61850 server: retrun object-access-unsupported when ctlModel is status-only
7 years ago
Michael Zillgith e9936b1d0e - modelviewer: show full hierarchy including sub data objects 7 years ago
Michael Zillgith 4dc0f9c987 - .NET API: Added support for IedConnection.GetState and StateChangedHandler 7 years ago
Michael Zillgith 618a84d37c - IEC 61850 client: add public header for function ControlObjectClient_createEx to create a client control object without the need to request information from the server 7 years ago
Michael Zillgith 91c22b3193 - IEC 61850 server: added IedServer_updateCtlModel function to change control model at runtime 7 years ago
Michael Zillgith cad88b67a1 - IEC 61850 client: fixed bug in new control object client implmentation - missing free for oper variable specification 7 years ago
Michael Zillgith 89d623866e - IEC 61850 client: add function IedConnection_getFileAsync 7 years ago
Michael Zillgith aca462c761 - removed outcommented code 7 years ago
Michael Zillgith f78f338b49 - IEC 61850 client: added implementations for functions IedConnection_getLogicalDeviceVariables, IedConnection_getLogicalDeviceDataSets, and IedConnection_getLogicalDeviceDataSetsAsync to address #89 7 years ago
Michael Zillgith e5be822032 - .NET API: DataSet implements IDisposable interface, Report/DataSet GetValues methods return now clones of the original native values to prevent GC issues 7 years ago
Michael Zillgith 4ba6d9903d - .NET API: MmsValue - added Clone method and implemented IDisposable interface 7 years ago
Michael Zillgith d0f4c06d62 - IEC 61850 client: added functions IedConnection_getLogicalDeviceVariables, IedConnection_getLogicalDeviceDataSets, and IedConnection_getLogicalDeviceDataSetsAsync to address #89 7 years ago
Michael Zillgith 154b3623e7 - .NET API: Added method MmsConnection.ReadMultipleVariables
- .NET API: extended MmsValue.ToString method to print arrays and data access errors
7 years ago
Michael Zillgith d5df360f3a - fixed problem in GOOSE publisher payload length calculation 7 years ago
Michael Zillgith a817b3d3c6 - updated data model of server_example_basic_io
- common: MmsVariableSpecification_getChildValue now also accepts "." as separator
7 years ago
Michael Zillgith 2c5fb89449 - IEC 61850 client: implemented tissue 1178 client side (select-response+ is non-NULL) 7 years ago
Michael Zillgith 33ce512c47 - Ethernet HAL Linux: limited interface name in Ethernet_getIntefaceMACAddress to prevent #83 7 years ago
Michael Zillgith 46211a01e7 - IEC 61850 client: IedConnection - added CONNECTING AND CLOSING states - removed IDLE state (now only CLOSED) 7 years ago
Michael Zillgith e12113acde - IEC 61850 client: implemented IedConnection_installStateChangedHandler 7 years ago
Michael Zillgith 43e0fb4d05 - IEC 61850 Client: ControlObjectClient - added async control actions 7 years ago
Michael Zillgith 1cc350ed4a - IEC 61850 client: implemented IedConnection_writeDataSetValuesAsync 7 years ago
Michael Zillgith c04b4e928d - IEC 61850 client: implemented IedConnection_readDataSetValuesAsync 7 years ago
Michael Zillgith 5ef3acc3e6 - added error handling in iec61850_client_example4 7 years ago
Michael Zillgith 8f4af64685 - SV: added API export attribute to new SV functions 7 years ago
Michael Zillgith 1eaf43ac8b - SV: fixed RefrTm and SmpSynch handling in SV publisher 7 years ago
Michael Zillgith 14e3a9668c - GOOSE publisher: fixed bug in GOOSE message calculation 7 years ago
Michael Zillgith f644b8d777 - IEC 61850 client: ControlObjectClient - avoid crash when "ctlVal" is not present in "Oper", also accept "setMag" instead of "ctlVal". 7 years ago
Michael Zillgith 23208aa066 - .NET API: ReportControlBlock.GetOwner returns null when no owner available (#79) 7 years ago
Michael Zillgith c9fe177a87 - IEC 61850 server: fixed potential deadlock in report processing 7 years ago
Michael Zillgith 861c5b244b - MMS client: fixed bug with async request timeout 7 years ago
Michael Zillgith cf63ab1269 - .NET API: IedConnection - add async QueryLog functions 7 years ago
Michael Zillgith 916f9da92e - .NET API: IedConnection - added new method GetLogicalDeviceVariablesAsync and property MaxPduSize 7 years ago
Michael Zillgith 0ff713b7f1 - .NET API: added async versions for WriteValaue and GetServerDirectory 7 years ago
Michael Zillgith 836892849c - IEC 61850 client: improved support for segmented report handling 7 years ago
Michael Zillgith e90d5d44fa - IEC 61850 client: added async discovery functions 7 years ago
Michael Zillgith 1d120f87de - .NET API: Added IedConnection.ReadValueAsync method 7 years ago
Michael Zillgith 44d8ad8d15 - IEC 61850/MMS client: changed all invokeId parameters in async callbacks to uint32_t 7 years ago
Michael Zillgith 7415fbc8da - .NET API: Added ReportControlBlock.GetOwner method (#79) 7 years ago
Michael Zillgith 871c63ad68 - .NET API: added some additional wrapper code for MmsVariableSpecification functions 7 years ago
Michael Zillgith 18cc25f1ff - added C# example code for client side setting group handling 7 years ago
Michael Zillgith 9925d98101 - fixed bug in cmake file (winpcap support) - (#78) 7 years ago
Michael Zillgith ed75aa3f46 - some code formatting 7 years ago
Michael Zillgith 46437cdbe1 - Java SCL parser: added support for timestamp values in "Val" elements 7 years ago
Michael Zillgith 7ec38e9615 - IEC 61850 client: added async client side RCB handling 7 years ago
Michael Zillgith 2b7dc5c5fe - added API export/internal decorations
- removed .def files for windows
7 years ago
Michael Zillgith 5201473262 - IEC 61850 client: added more prototypes for async client API 7 years ago
Michael Zillgith e6884d721b - IEC 61850 client: added asynchronous query log functions 7 years ago
Michael Zillgith a14d39e2e2 - .NET API: fixed wrong defintion for ClientReportControlBlock_getResvTms in ReportControlBlock class 7 years ago
Michael Zillgith ea20cb2081 - .NET API: Added missing access functions for ResvTms to ReportControlBlock class (#74) 7 years ago
Michael Zillgith 9eb8b17002 - python wrapper: some changes in cmake file 7 years ago
Cengiz Kaygusuz e8ea5f142f Add .gitignore, ignore build/ 7 years ago
Michael Zillgith 54d8fb74d7 - IEC 61850 client: added async versions for connect, abort, release, get variable specification, write object 7 years ago
Michael Zillgith a5e15003ce - correcting verions detection for swig (phyton)
- client: adopted TLS code to new async architecture
7 years ago
Michael Zillgith 56d7ee4f0b - IEC 61850/MMS client: Add support for write variable for array element with component
- added lost README file for winpcap
7 years ago
Michael Zillgith 70c1cd691d - MMS client: refactoring for async connect, abort, release 7 years ago
Michael Zillgith 8d45d44cc2 - Socket HAL: added functons for asynchronous (non-blocking) connect 7 years ago
Michael Zillgith 4d32e3c1ae - MMS client: code cleanup for asnyc functions 7 years ago
Michael Zillgith 069646f954 - MMS client: added asynchronous file service functions 7 years ago
Michael Zillgith d9800a5f74 - Windows Ethernet Hal: fixed memory leak 7 years ago
Michael Zillgith 9d26990313 - Java tools: fixed bug in SCL parser (wrong interpretation of numbers with leading "0" 7 years ago
Michael Zillgith 7767e282d6 - MMS client: added asynchronous get name list functions 7 years ago
Michael Zillgith fc1d62d1a7 MMS client: added asynchronous read journal service 7 years ago
Michael Zillgith c80a87d5e8 - MMS client: add asynchronous function for MMS identify service 7 years ago
Michael Zillgith 7600c0f3cf - MMS client: add asynchronous function for MMS status request service 7 years ago
Michael Zillgith aa7e89684e - MMS client: add asynchronous function for get variable access attributes service 7 years ago
Michael Zillgith 5692d0246b - MMS client: added asynchronous define named variable list functions 7 years ago
Michael Zillgith 80ce9c8967 - MMS client: added asynchronous read and write functions 7 years ago
Michael Zillgith 026357b5eb - added doxygen files for .NET API 7 years ago
Michael Zillgith 6ba363bd4a - updated changelog for release 1.3.0 7 years ago
Michael Zillgith bed67e4f50 - added missing function definition in DLL export files 7 years ago
Michael Zillgith aa86d3b259 - IEC 61850 server: number of dynamic data sets configurable at runtime 7 years ago
Michael Zillgith a0adcf94e7 - IEC 61850 Server: made number of data set entries configurable at runtime 7 years ago
Michael Zillgith 2f0211b188 - GOOSE publisher example: fixed memory leak 7 years ago
Michael Zillgith c0ce64c758 - file-tool: file client example is now compatible with windows 7 years ago
Michael Zillgith a830fc3cfb - IEC 61850 server: reporting - don't delete pending events when buffered report is enabled and dataset didn't change 7 years ago
Michael Zillgith e905bc242b - MMS server: initialize maxConnections in IsoServer 7 years ago
Michael Zillgith 77f97dc006 - replaced strndup 7 years ago
Michael Zillgith 51c29fe9a7 - IEC 61850 server/ MMS server: maximum number of client connections configurable at runtime 7 years ago
Michael Zillgith e980a519ae - IEC 61850 server: control objects - fixed bug in select response for SBO control model 7 years ago
Michael Zillgith d108dae115 - MMS server: fixed locking bug in file obtain service 7 years ago
Michael Zillgith 2585aab516 - cleanup examples makefiles
- fixed bug in MMS mapping read handler
7 years ago
Michael Zillgith d0061fce96 - updated ICD file for server_example_complex_array
- added client example for array handling
7 years ago
Michael Zillgith 8b957b8f82 - IEC 61850 client: add support for single array element access (with component specification) 7 years ago
Michael Zillgith eef34cf40e - MMS server: add support for array element (index) access with nested component 7 years ago
Michael Zillgith 26af0d93c2 - IEC 61850 server: made IEC 61850 edition configurable at runtime 7 years ago
Michael Zillgith 6199da1e55 - IEC 61850 server: CONFIG_REPORTING_SUPPORTS_OWNER replaced by CONFIG_IEC61850_EDITION_1 7 years ago
Michael Zillgith 14c8434201 - server_example_basic_io: fixed ICD/CID file 7 years ago
Michael Zillgith e7905cc16b - IEC 61850 server: memory handling optimization in control module 7 years ago
Michael Zillgith 020b1f40aa - IEC 61850 server: integrated automatic handling of "origin" and "ctlVal" status (ST) values for controllable CDCs 7 years ago
Michael Zillgith 713ca54cd0 - IEC 61850 server: optimized dynamic memory management in control handling; memory will be initialized at server start 7 years ago
Michael Zillgith 6618093f7a - IEC 61850 server: functions IedModel_getModelNodeByShortObjectReference and IedModel_getModelNodeByObjectReference now also work with object references that have only LD part 7 years ago
Michael Zillgith 3f07176dc3 - MMS server: fixed bug in delete variable list service - scope of delete was not considered optional 7 years ago
Michael Zillgith 58b4d6c107 -IEC 61850 server: added ReadAccessHandler to control read access 7 years ago
Michael Zillgith 0b51d6841a - added Socket_activateTcpKeepAlive function 7 years ago
Michael Zillgith 02cda48128 - moved TLS API to platform abstraction layer 7 years ago
Michael Zillgith 9995a7cfc4 - IEC 61850 client: fixed bug in select response handling 7 years ago
Michael Zillgith 4d8e256967 - .NET API: Added array/structure handlung functions to MmsValue 7 years ago
Michael Zillgith 71493036dc - IEC 61850 server/MMS server: make dynamic data set service configurable at runtime with IedServerConfig object (new functions IedServerConfig_enableLogService and IedServerConfig_isLogServiceEnabled) 7 years ago
Michael Zillgith 0a3d86601b - IEC 61850 server/MMS server: make dynamic data set service configurable at runtime with IedServerConfig object (new functions IedServerConfig_enableDynamicDataSetService and IedServerConfig_isDynamicDataSetServiceEnabled) 7 years ago
Michael Zillgith 27e883a1bc - MMS server: fixed bug in association service (file rename was not reported as supported service) 7 years ago
Michael Zillgith 143bc977c0 - IEC 61850 server/MMS server: make file service configurable at runtime with IedServerConfig object (new functions IedServerConfig_enableFileService and IedServerConfig_isFileServiceEnabled) 7 years ago
Michael Zillgith af35ee17fa - removed unused code 7 years ago
Michael Zillgith e6765585cf - updated cmake file for hal to compile with Visual Studio 7 years ago
Michael Zillgith de04f3630b - moved lib_memory to hal project 7 years ago
Michael Zillgith 7d890b7450 - updated version to 1.3.0 7 years ago
Michael Zillgith 210a81d14e - updated Makefiles for separate HAL 7 years ago
Michael Zillgith 2f71744079 - added serial port hal
- moved hal to separate directory
- added new hal cmake project
7 years ago
Michael Zillgith dc4fbd76ad - unification of HAL with lib60870 7 years ago
Michael Zillgith c36050f455 - renamed iec61850_client_example3 to iec61850_client_example_control
- removed outcommented code
7 years ago
Michael Zillgith b5cb80868c - IED SERVER: fixed bug when calling write access handler (when access policy DENY) 7 years ago
Michael Zillgith eacdfa953d - IED SERVER: fixed bug when calling write access handler (wrong pointer for ClientConnection object) 7 years ago
Michael Zillgith 47d34702b1 - updated IEC 61850-9-2 LE example to be more realistic 7 years ago
Michael Zillgith 2e160d6279 - added server side example for the substitution service 7 years ago
Michael Zillgith 77c4d3ae03 - 9-2LE example: updated data set 7 years ago
Michael Zillgith 894ea2e726 - SV: added function SVPublisher_ASDU_setSmpCntWrap
- added quality flag "derived"
- updated 9-2LE publisher example
7 years ago
Michael Zillgith 5de644b3bc - .NET API: added check for maximum size of s-selector 7 years ago
Michael Zillgith ab51835377 - MMS server: fixed wrong preprocessor defines that can cause problems in some configurations (unlimited number of client connections/ multi-threaded server) 7 years ago
Michael Zillgith a7cb12f5b0 - IEC 61850 client: added new function ControlObjectClient_getCtlValType to simplify control handling 7 years ago
Michael Zillgith 4605c60a3b - fixed bug in MmsValue_update 7 years ago
Michael Zillgith 2119503cbf - Visual Studio support: added missing export definitions for client side GoCB handling 7 years ago
Michael Zillgith 5064c9c31c - updated java binaries 7 years ago
Michael Zillgith 2c193fed6e Merge branch 'v1.2' of https://github.com/mz-automation/libiec61850 into v1.2 7 years ago
Michael Zillgith 9cb032138b - Java SCL parser: parser is more tolerant. Added access to IED list. 7 years ago
Michael Zillgith a54c5ebca2
Merge pull request #68 from synexxus/installdirs-cmake-update
Use GNUInstallDirs for install location on Linux
7 years ago
Robert Middleton 9fce1a342a Use GNUInstallDirs for install location on Linux 7 years ago
Michael Zillgith 49d06cc9d3 - NET API: added TLS support for server side 7 years ago
Michael Zillgith 38ee7b43ef - updated version to 1.2.2 7 years ago
Michael Zillgith 56046beebe - updated project file for .NET core 7 years ago
Michael Zillgith 48b14619a3 - .NET API: Added IedServerConfig class 7 years ago
Michael Zillgith cc24c86484 - Fixed to compile with C++ 7 years ago
Michael Zillgith c28d06f4d8 - IEC 61850 server: added support to set file service base path with server configuration object 7 years ago
Michael Zillgith 7cb5ff670a - IEC 61850 server: added support to configure report buffer at runtime
- IEC 61850 server: new IedServerConfig type and new IedServer constructor
7 years ago
Michael Zillgith fe4ae3f38f Merge branch 'v1.2' of https://github.com/mz-automation/libiec61850 into v1.2 7 years ago
Michael Zillgith 9a8415b3e6 - IEC 61850 server: prevent sending reports when data model is locked (updated) 7 years ago
Michael Zillgith 7ff48e85c5
Merge pull request #63 from arthurazs/v1.2
- Update content list from README
7 years ago
Michael Zillgith 2c9a4bb088 - TLS client: fixed problem with high CPU load 7 years ago
Michael Zillgith 9e15185c74 - ISO connection: fixed race condition that can cause corrupted messages 7 years ago
Michael Zillgith 605913b0c1 - fixed some configuration issues 7 years ago
Michael Zillgith a451731454 - IEC 61850 server: removed unnecessary dynamic string allocation 7 years ago
Arthur Zopellaro 2e434d8d47 Update content list
Add missing items from content list
Add anchor link to each section
7 years ago
Michael Zillgith 1ac2a7390f - .NET API: updated marshalling for GooseControlBlock 7 years ago
Michael Zillgith cab1f783fd - .NET API: added project files for .NET core 2.0 7 years ago
Michael Zillgith eb97d64ae2 - .NET API: updated marshaling of bool types in pinvoke code 7 years ago
Michael Zillgith 731608e5b0 - removed inline qualifier from MemoryAllocator_getAlignedSize 7 years ago
Michael Zillgith da17f8210a - updated version to 1.2.1 7 years ago
Michael Zillgith cf049071cc - IEC 61850 server: fixed bug in report module when RCB was enabled multiple times (new in 1.2.0) 7 years ago
Michael Zillgith 76ab1ec9f6 - .NET API: Added destructor and Dispose method to ReportControlBlock
- .NET API: Changed ReportControlBlock access to IedConnection to improve stability when connection closes unexpectedly
7 years ago

@ -0,0 +1,26 @@
name: CIFuzz
on: [pull_request]
jobs:
Fuzzing:
runs-on: ubuntu-latest
steps:
- name: Build Fuzzers
id: build
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
with:
oss-fuzz-project-name: 'libiec61850'
dry-run: false
language: c
- name: Run Fuzzers
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
with:
oss-fuzz-project-name: 'libiec61850'
fuzz-seconds: 300
dry-run: false
language: c
- name: Upload Crash
uses: actions/upload-artifact@v3
if: failure() && steps.build.outcome == 'success'
with:
name: artifacts
path: ./out/artifacts

@ -0,0 +1,71 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ v1.5 ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ v1.5 ]
schedule:
- cron: '38 23 * * 6'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'cpp' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2

@ -0,0 +1,12 @@
name: Greetings
on: [pull_request, issues]
jobs:
greeting:
runs-on: ubuntu-latest
steps:
- uses: actions/first-interaction@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
pr-message: 'Push requests and other code contributions can only be accepted from authorized persons that have signed our contributor license agreement(CLA). When in doubt please write to info@libiec61850.com.'

2
.gitignore vendored

@ -0,0 +1,2 @@
build/
/Debug/

@ -1,3 +1,369 @@
Changes to version 1.5.3
------------------------
New features and improvements:
- config file parser dynamically allocates linebuffer to allow multithreaded applications (#484)
- parse time values in model configuration file (LIB61850-426)
- config file generator: added missing code for GSEControl (LIB61850-418)
- Config file generator: support multiple access points for GOOSE and SMV control blocks (LIB61850-418)
- config file generator: added code to add SMVCBs to config files (LIB61850-67)
- IED server: added code to create SMVCBs with the dynamic model API (LIB61850-67)
- MMS server: added support for write access with component alternate access (LIB61850-414)
- MMS client: added function MmsConnection_writeVariableComponent to write to variables with alternate component access (LIB61850-414)
- make write access to RCB elements configurable according to ReportSettings (LIB61850-404)
- Added function IedConnection_setLocalAddress to define local IP address and optionally local port of a client connection (LIB61850-378)
- IED server: added ControlAction_getSynchroCheck and ControlAction_getInterlockCheck functions
Fixed bugs and vulnerabilities:
- fixed - IEC 61580 server: dataset is not released when RCB.Datset is set to empty string by client (LIB61850-425)
- PAL: fixed wrong order of function arguments for fread and fwrite functions
- MMS client: parsing of servicecsSupported in MMS init response is off by one (LIB61850-419)(#469)
- fixed - potential memory leaks in goose publisher code (#464)
- fixed - server sends dchg report when only dupd is enabled in RCB (LIB61850-411)
- GOOSE subscriber: fixed - possible heap corruption in parseAllData due to missing validity check in bit-string handling (LIB61850-402)
- IED server: fixed problem with implicit ResvTms setting when reserved with RptEna (LIB61850-400)
- IED server: fixed - segmentation fault when compiled with CONFIG_MMS_THREADLESS_STACK (LIB61850-398)
- fixed - MMS server: messages can be corrupted when TCP buffer is full (LIB61850-385)
- fixed - .NET: IedConenction.WriteDataSetValues throws a NullReferenceException (LIB61850-384)
- fixed - server send invalid response- when client uses wrong ctlModel (LIB61850-383) (#435)
- fixed - IedConnection_setRCBValuesAsync crashes when RCB is already reserved by other client (LIB61850-382)
- fixed - outstanding call not released in IedConnection_getDataSetDirectoryAsync (LIB61850-379)
Changes to version 1.5.2 (Dec 19, 2022)
---------------------------------------
New features and improvements:
- renamed TLSConfiguration_EventLevel to TLSEventLevel
- updated required mbedtls version to 2.28.x
- Added check for changed CRL on socket read/write. Added reset of renegotiation ssl cache on CRL add
- Fixing Security events messages to match IEC62351-100-3
- .NET API: Added support for TLS event handler (LIB61850-373)
- IED Server: added function to set time quality for internally updated times (LIB61850-372)
- added TLSConnection object to provide more context in TLS event callback (LIB61850-366)
- TLS: added TLS alert callbacks; support for session resumption with session IDs (LIB61850-339)
- MMS client: added function MmsConnection_sendRawData for test purposes
- changed StringUtils_createStringInBuffer function to consider max buffer size (LIB61850-333)
- replaced most str(n)cpy/str(n)cat calls (LIB61850-333)
- encode boolean true value as 0x01 instead of 0xff to avoid interoperability problems
- added IedServerConfig_setSyncIntegrityReportTimes/IedServerConfig_setSyncIntegrityReportTimes wrapper to .NET API (LIB61850-323)
- added feature: synchronization of integrity report times (LIB61850-323)
- server: added RCBEventHandler event types REPORT_CREATED and OVERFLOW
- added function ReportControlBlock_getResv
- mms_utility: added option to read data set directory
- .NET API: added IedServer.GetFunctionalConstrainedData method (LIB61850-317)
- RCBEventHandler: replaced GI event by purgeBuf event when client disables RCB instance (LIB61850-316)
- enabled TLS 1.2 support in mbedtls configuration
- improved MmsValue handling; fixed MmsValue(OCTET-STRIG) maximum size problem (LIB61850-150)
- IED server: improved control state machine performance (LIB61850-312)
Fixed bugs and vulnerabilities:
- fixed - dynamic model helper functions: Check added to Cancel object for CDC APC
- fixed wrong number in TLS event code define (LIB61850_366)
- fixed - servers sends object-access-unsupported on GetAllData when ReadAccessHandler is installed (LIB61850-370)
- fixed - endless loop sending reports when MMS PDU size is too small (LIB61850-365)
- fixed path traversal vulnerability in MMS file services (LIB61850-357)
- IED server: added missing call to getNextRoundedStartTime (LIB61850-323)
- fixed - server crashs when SyncIntegrityReportTimes is active and IntgPd=0 (LIB61850-355)
- fixed - missing API export declarations for functions IedServerConfig_setSyncIntegrityReportTimes and IedServerConfig_getSyncIntegrityReportTimes (LIB61850-353)
- IED server: fixed - possible deadlock when IedServer_lockDataModel is used from multiple threads (LIB61850-352)
- MMS server: fixed - possible deadlock in obtainFile-service/file upload task (LIB61850-351)
- MMS server: fixed potential null pointer dereference when confirmeServiceResponse for fileOpen is received with invoke-id 0 (LIB61850-348)
- MMS_SERVER: fixed bug in getNameList request handling when domain ID is too long (LIB61850-346)
- GOOSE subscriber: fixed vulnerabilities related to malformed bit-string, integer, and unsigned values (LIB61850-342)
- MMS server: fixed bug in handling of continueAfter parameter of getNameList request (LIB61850-341)
- fixed sscanf format string in config_file_parser.c
- fixed locking mechanism in logging.c (LIB61850-327)
- fixed problem: negative presentation layer and ACSE results are ignored by client
- fixed wrong buffer size in client side report handling
- fixed memory leak in server read request handling (LIB61850-325)
- fixed memory leak in reuse of client connection (related to socket extension buffer)
- fixed - TLS: CRL is ignored
- fixed wrong MMS protocol version check (#379)
- fixed - SV publisher encoding problem when svID or datset length > 127 bytes (LIB61850-315)(#382)
- IedServerConfig: added missing variable initialization
- fixed - server doesn't respond SBOw when waiting for select callback (LIB61850-313)
Changes to version 1.5.1 (Mar 11, 2022)
---------------------------------------
New features and improvements:
- added server side ReportControlBlock events and value access functions
- added functions Timestamp_fromMmsValue and Quality_toMmsValue
- made server report reservation compatible with Ed. 2.1 (LIB61850-293)
- new functions MmsValue_getOctetStringOctet and MmsValue_setOctetStringOctet
- IedConnection: added function IedConnection_getDataSetDirectoryAsync
- IedConnection: added function IedConnection_createDataSetAsync
- IedConnection: added new function IedConnection_deleteDataSetAsync
- IedServer instance can be restarted
- new function IedConnection_setTimeQuality - Added support to set time quality for client generated time stamps (LIB61850-280)
- .NET API: added wrapper for IedConnection_setFile and IedConnection_setFilestoreBasepath (LIB61850-258)
- IED server: improved accuracy of integrity report intervals
- .NET API: GooseSubscriber - added GetGoId, GetGoCbRef, GetFataSet methods
- IED server: add support for SMV control blocks ("SMVC") in config file parser
- .NET API: added support for server integrated GOOSE publisher
- MacOS thread layer: replaced semaphore by mutex
Fixed bugs and vulnerabilities:
- fixed vulnerability of GOOSE subscriber to malformed messages (LIB61850-304)
- fixed - Bug in presentation layer parser can cause infinite loop (LIB61850-302)
- .NET API: fix problem with garbage collected delegates for async client functions (LIB61850-301)
- fixed compilation problem with option CONFIG_MMS_THREADLESS_STACK
- fixed - TPKT error when connection is interrupted during message reception (LIB61850-299)
- handle presentation layer data messages with transfer-syntax-name
- fixed - UBRB: library can't work at the same time with URCB with preconfigured client and URCB without preconfigured client (LIB61850-292)(#355)
- fix - server crashes when presentation message has no user data (LIB61850-291)(#368)
- MMS server: query log service returns services error instead of reject message when log does not exist (LIB61850-290)
- fixed - IED server: crash during invalid control access - FC=CO on invalid layer (LIB61850-282)
- fixed - Server: ctlNum and origin(status) are not updated automatically by the server when APC command is received (LIB61850-277)
- MMS server: fixed problem with continue-after in some get-name-list handling cases
- fixed - IedConnection: outstanding call on IEC layer is not release under some circumstances (LIB61850-270, LIB61850-251)
- fixed bug in IsoServer that caused memory violation when the server was restarted while a client was connected
- IED client: send RptEna as first element when RCB is to be disabled
- fixed problem with double free of TLS configuration structure (LIB61850-254)
- .NET API: Fixed problem with AccessViolationException in GooseControlBlock.GetDstAddress
- MMS server: fixed data race bug in transmitBuffer handling (#338)
- IED server: fixed crash when IEDName+LDInst is too long
- .NET API: fixed bug - server write access handler causes "CallbackOnCollectedDelegate" exception (LIB61850-236)
- MMS server: fixed potential crash when client connection closed during file upload (LIB61850-2)
- MMS client: fixed problem - doesn't close file when the setFile (obtainFile) service is interrupted e.g. due to connection loss (LIB61850-230)
- Ethernet Socket (Windows): fixed bug and added workaround for problem on Windows (most GOOSE/SV messages are not received when waiting with WaitForMultipleObjects - observed with winpcap 4.1.3 and Windows 10
- fixed problem in BER integer decoder (problem with GOOSE fixed length message decoding)
- .NET API: Fixed memory release problem in method ModelNode.GetObjectReference
- IED server: fixed bug in GoCBEventHandler
- fixed problem in BSD ethernet layer (#328)
- fixed bug in cmake file for BSD
- fixed compilation problem when compiling without GOOSE support (#325)
- IED server: control handling - fixed problem in test flag handling
- IED server: For SBOes check test flag match when accepting operate (sSBOes8)
- IED server: Reject Cancel/SBOw in WaitForChange state - fixed problem with test case sCtl26
Changes to version 1.5.0
------------------------
- added support for time with ns resolution
- IEC 61850 server: control models - allow delaying select response with check handler (new handler return value CONTROL_WAITING_FOR_SELECT)
- IEC 61850 server: added support to listen on multiple IP addresses and ports (new function IedServer_addAccessPoint)
- added support for service tracking
- added tool support for transient data objects
- .NET API: added more functions to create and access server data model
- IED server - control model - send AddCause with operate- for DOes, SBOes control models
- IED server: integrated GOOSE publisher - lock data model during GOOSE retransmission to avoid corrupted GOOSE data
- added server example for dead band handling
- IED server: make presence of RCB.Owner configurable at runtime with function IedServerConfig_enableOwnerForRCB (B1502/S1634)
- IED server: make presence of BRCB.ResvTms configurable at runtime with function IedServerConfig_enableResvTmsForBRCB (F1558)
- restrict maximum recursion depth in BerDecoder_decodeLength when indefinite length encoding is used to avoid stack overflow when receiving malformed messages
- fixed oss-fuzz issues 31399, 31340, 31341, 31344, 31346
- IED server: fixed bug in log service - old-entry and old-entry-time not updated
- IED server: added new function IedServer_handleWriteAccessForComplexAttribute. Changed WriteAccessHandler behavior when ACCESS_POLICY_ALLOW.
- MMS server: add compile time configuration options to enable/disable fileDelete and fileRename services (fileRename is now disabled by default)
- MMS server: better data model lock handling for performance improvements
- Linux - Ethernet: replace IFF_PROMISC by IFF_ALLMULTI
- improvements in Python wrapper code
- IED server: control models - fixed bug that only one control is unselected when connection closes
- IED server: fixed bug - logs (journals) are added to all logical devices instead of just the parents
- IED Server: prevent integrated GOOSE publisher to crash when ethernet socket cannot be created
- IED server: make compatible with tissue 1178
- IED server: reporting - implemented behavior according to tissue 1432
- IED server: WriteAccessHandler can tell the stack not to update the value when returning DATA_ACCESS_ERROR_SUCCESS_NO_UPDATE
- IED server: fixed problem that BL FC is not writable (#287)
- IEC 61850 client: fixed dead lock in IedConnection_getFileAsync when fileRead times out (#285)
- IED server: added ControlSelectStateChangedHandler callback for control mode
- Client: fixed - IedConnection_getRCBValues doesn't check type of server response (#283)
- GOOSE subscriber: changed maximum GoID size according to tissue 770 (129 bytes)
- IED server: send AddCause for invalid origin also in case of direct control models
- IED server: support for configuration of EditSG service and online visibility of SGCB.ResvTms at runtime
- IED server: changed types TrkOps and OptFlds to variable length bit strings
- MMS: changed handling of variable sized bit strings (now also accepts bit strings of larger size, ignoring the bits that exceed the specified size)
- IED server: add support for correct CBB handling (required for test case sAss4) and initiate error PDU
- IED server: add support for tissue 807 (owner attribute in RCB is only present when ReportSettings@owner attribute is true)
- IED server: implemented tissue 1453 also for writing to "RptId" (purgeBuf only executed when value changes)
- GOOSE subscriber: always copy GoID and DatSet from GOOSE message; always create new MmsValue instance for GOOSE data set when subscriber is observer
- IED server: added configuration file support for data set entries with array elements or array element components
- fixed problems in handling array elements and array element components
- fixed bug in MmsConnection_readMultipleVariables: send invaid messsage and memory access errors when too many items are passed to the function exhausting MMS payload size
- IEC 61850 server: fixed problem with test case sRp4 - RCB RptID attribute is not empty after writing empty string
- fixed program crash when normal mode parameers are missing in presentation layer (#252)
- IED Server/GOOSE: Don't send GOOSE message with new event while data model is locked
- GOOSE: added GOOSE observer feature (GooseSubscriber listening to all GOOSE messages) and GOOSE observer example
- COTP: fixed possible heap buffer overflow when handling message with invalid (zero) value in length field (#250)
- IEC 61850 server: fixed - cancel command for time activated control returns object-access-denied even in case of success
- IEC 61850 client: fixed bug - IedConnection_setRCBValuesAsync always return 0 instead of invoke-ID
- MMS: fixed problem in handling of indefinite length encoded BER elements
- IEC 61850 client: reporting - support data set entries with multiple reasons for inclusion
- Java tools: moved minTime, maxTime from GSEControl to GSE; updated GOOSE server example CID file
- IEC 61850 server: Added ControlAction_setError function - with this function the user application can control the error code used in LastApplError and CommandTermination messages
- IEC 61850 server: fixed problem with logging when log data set contains FCDO (#225)
Changes to version 1.4.2.1
--------------------------
- IEC 61850 server: RCB - fixed problem that other client can "steal" reservation
- MMS client: fixed bug in log entry parsing (#224)
- IEC 61850 server: fixed potential null pointer dereference in multi-thread mode when server is stopped
- IEC 61850 server: fixed bug in single threaded mode (windows)
- IEC 61850 server: fixed compilation error in single thread mode (was new in release 1.4.2)
Changes to version 1.4.2
-------------------------
- IEC 61850 server: wait for background thread termination before data model is released
- MMS server: fixed potential crash when get-named-variable-list-attributes response doesn't fit in MMS PDU. Server returns service error in this case
- IEC 61850 server: unbuffered reporting - send first integrity report after integrity timeout (before it was sent when the RCB was enabled)
- IEC 61850 server: allow server to start without logical devices in data model (#218)
- IEC 61850 client: fixed bug in ClientReportControlBlock - some allowed structures for RCB were rejected
- IEC 61850 server: control - unselect when operate with wrong origin parameters, check if check parameter matches for SBO
- IEC 61850 server: fixed missing report timestamp update for unbuffered reporting
- IEC 618580 server: Added function IedServer_setServerIdentity to set values for MMS identity service
- CDC helpers: added functions to create ISC and BAC CDCs
- CDC helpers: added stSeld and attributes from ControlTestingCDC to control CDCs
- CDC helper functions: added stSeld and attributes from ControlTestingCDC to control CDCs
- updated cmake files
- .NET API: fixed memory management issue in MmsValue.SetElement (see #213)
- IEC 61850 server: unselect control when oper is not accepted
- IEC 61850 server: send select-failed for control when origin parameter is not valid
- IEC 61850 server: fixed control handling to comply with test case sCtl25
- IEC 61850 server: fixed control handling to comply with test case sCtl11
- IEC 61850 server: pass origin, ctlNum, ctlVal to select handler (perform check handler) for SBOw
- removed internal header files from install target (#214)
- .NET API: additional function mappings
- TLS: fixed memory leak when TLS authentication fails
- fixed bug in windows socket layer
Changes to version 1.4.1
------------------------
- MMS server: refactored connection handling; more efficient use of HandleSet
- linux/bsd socket layer: replaced select by poll
- removed header dependencies from API headers
- IEC 61850 server: added support for transient data objects
- .NET API: added MmsValue methods BitStringToUInt32BigEndian and BitStringFromUInt32BigEndian
- fixed compilation problem when CONFIG_MMS_THREADLESS_STACK is defined
- MMS get name list service: fixed wrong return value in case of unknown argument for continueAfter (problem with test case sSrvN1)
- fixed memory leak in windows socket layer (socket connect)
- improved robustness in MMS message parsing
- SV publisher: fixed memory leaks (#191)
- .NET API: added ControlAction.GetControlTime methods
- .NET API: fixed problem in ReportControlBlock.SetRCBValues (see #184)
- MMS server: fixed possible crash when client disconnects during file upload
- MMS server: fixed file upload error with multi-threaded server, added some NULL checks to file-handling.
- IEC 61850 server: added function ConfigFileParser_createModelFromConfigFileEx with filename as argument to avoid dependency on FileSystem_... functions
- IEC 61850 server: Add check call before starting a timeactivated operate, so operates can be denied before the waiting state
- IEC 61850 client: improved error handling and fixed potential memory leak in IedConnection_getDeviceModelFromServer
- replaced timegm implementation on windows. Fixes bug with MMS file times
Changes to version 1.4.0
------------------------
- IEC 61850 client: added asynchronous client API (can handle multiple outstanding requests in a single thread)
- IEC 61850 client: added support for non-thread mode (for use with asynchronous API)
- IEC 61850 client: added IedConnection_StateChangedHandler callback that is called for each connection state change
- .NET API: Added support for IedConnection.GetState and StateChangedHandler
- modelviewer: show full hierarchy including sub data objects
- IEC 61850 server: added IedServer_updateCtlModel function to change control model at runtime
- IEC 61850 client: added functions IedConnection_getLogicalDeviceVariables, IedConnection_getLogicalDeviceDataSets, and IedConnection_getLogicalDeviceDataSetsAsync to address #89
- .NET API: extended MmsValue.ToString method to print arrays and data access errors
- common: MmsVariableSpecification_getChildValue now also accepts "." as separator
- .NET API: ReportControlBlock.GetOwner returns null when no owner available (#79)
- IEC 61850 client: IedConnection - added CONNECTING AND CLOSING states - removed IDLE state (CLOSED, CONNECTING, CONNECTED, CLOSING)
- now using mbedtls 2.16
- TLS renegotiation disabled by default
- fixed bug in BerInteger_setUint16
- IEC 61850 client: Added functions IedConnection_setRequestTimeout and IedConnection_getRequestTimeout to C API and IedConnection.RequestTimeout property to .NET API
- MMS client: fixed problem with obtain file timeout with large files
- IEC 61850 server: Control model callback signature changed. Added ControlAction object to access control related parameters in control callbacks
- SV subscriber: improved error handling when Ethernet access doesn't work; fixed potential memory leak
- GOOSE publisher: integrated error handling when Ethernet interface is not available
- GOOSE receiver: add support for operation without Ethernet HAL implementation
- MMS server: fixed memory access problem when client unexpectedly closed connection during file upload (set-file)
- static model generator: Initialize Dbpos value from Val element in ICD/CID file (see github #163)
Changes to version 1.3.3
------------------------
- IEC 61850 server: reporting - fixed problem with removing old GI reports when latest report is also GI
- IEC 61850 client: fixed problems in ClientReportControlBlock_create (see github #134)
- IEC 61850 client: handle reason code correctly when report contains data with different reason code (see github #133)
- IEC 61850 server: optimized report buffer handling for buffered reporting (save memory and encoding time)
- IEC 61850 client: fixed problem - IedConnection cannot be reused after IedConnection_close (github #124)
- IEC 61850 server: added support for pre configured client with ClientLN
- IEC 61850 client: added function ClientReportControlBlock_hasResvTms
- IEC 61850 server: don't clear owner when client disables BRCB (RptEna = false)
- IED Server: added ResvTms handling for BRCB
- SV publisher: fixed length calculation
- IEC 61850 server: added support for segmented reporting
- fixed bug in windows socket abstraction
- fixed client TCP keep alive problem (see github #115)
- MMS server: read service - return data access error for component access to simple variable
- GOOSE receiver: fixed potential deadlock when GooseReceiver_stop is called directly after GooseReceiver_start
Changes to version 1.3.2
------------------------
- MMS client/server: added support for component alternate access for generic variable read requests
- MMS client: improved handling/stability when receiving malformed messages from the server
- IEC 61850 server: fixed problem with wrong purge buffer invocation when using dynamic data set in buffered report control block
- .NET API: add GetFileDirectoryEx function
- modelviewer: show full hierarchy including sub data objects
- .NET API: DataSet implements IDisposable interface, Report/DataSet GetValues methods return now clones of the original native values to prevent GC issues
- .NET API: MmsValue - added Clone method and implemented IDisposable interface
Changes to version 1.3.1
------------------------
- GOOSE publisher: fixed problem in payload length calculation
- .NET API: Added method MmsConnection.ReadMultipleVariables
- IEC 61850 client: implemented tissue 1178 client side (select-response+ is
non-NULL)
- SV publisher: fixed RefrTm and SmpSynch handling
- IEC 61850 client: improved support for handling segmented reports
- .NET API: Added some additional access function to ReportControlBlock
- Java SCL parser: added support for timestamp values in "Val" elements
- fixed bug in cmake file (winpcap support)
- added C# example code for client side setting group handling
- .NET API: added some additional wrapper code for MmsVariableSpecification functions
Changes to version 1.3.0
------------------------
- IEC 61850 server: more features configurable at runtime
- IEC 61850 server: control objects - fixed bug in select response for SBO control model
- IEC 61850 client: add support for single array element access (with component specification)
- MMS server: add support for array element (index) access with nested component
- IEC 61850 server: made IEC 61850 edition configurable at runtime
- IEC 61850 server: added ReadAccessHandler to control read access
- HAL: unified platform abstraction layer (to simplify using the library together with lib60870)
- IEC 61850 server: fixed bug when calling write access handler (wrong pointer for ClientConnection object)
- updated IEC 61850-9-2 LE example to be more realistic
- added server side example for the substitution service
- MMS server: fixed wrong preprocessor defines that can cause problems in some configurations (unlimited number of client connections/ multi-threaded server)
- IEC 61850 client: added new function ControlObjectClient_getCtlValType to simplify control handling
- IEC 61850 server: reporting - don't delete pending events when buffered report is enabled and dataset didn't change
- fixed bug in MmsValue_update
- MMS server: fixed bug in delete variable list service - scope of delete was not considered optional
- some more small bug fixes and optimizations
Changes to version 1.2.2
------------------------
- IEC 61850 server: added support to configure report buffer size at runtime
- IEC 61850 server: new IedServerConfig type and new IedServer constructor
- .NET API: added support for IedServerConfig
- IEC 61850 server: prevent sending reports when data model is locked (updated)
- TLS client: fixed problem with high CPU load
- ISO connection: fixed race condition that can cause corrupted messages
- .NET API: added project files for .NET core 2.0
- .NET API: added server side support for TLS
Changes to version 1.2.1
------------------------
- IEC 61850 server: fixed bug in report module when RCB was enabled multiple times (was new in 1.2.0)
- .NET API: Added destructor and Dispose method to ReportControlBlock (fixed memory leak)
- .NET API: Changed ReportControlBlock access to IedConnection to improve stability when connection closes unexpectedly
Changes to version 1.2.0
------------------------
@ -13,7 +379,6 @@ Changes to version 1.2.0
- SV subscriber: replaced code that caused unaligned memory access
- IEC 61850 server: added memory alignement for buffered reporting
Changes to version 1.1.2
------------------------

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 2.8)
cmake_minimum_required(VERSION 3.5.1)
# automagically detect if we should cross-compile
if(DEFINED ENV{TOOLCHAIN})
@ -11,8 +11,8 @@ project(libiec61850)
ENABLE_TESTING()
set(LIB_VERSION_MAJOR "1")
set(LIB_VERSION_MINOR "2")
set(LIB_VERSION_PATCH "0")
set(LIB_VERSION_MINOR "5")
set(LIB_VERSION_PATCH "3")
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/")
@ -33,16 +33,28 @@ option(BUILD_PYTHON_BINDINGS "Build Python bindings" OFF)
option(CONFIG_MMS_SINGLE_THREADED "Compile for single threaded version" ON)
option(CONFIG_MMS_THREADLESS_STACK "Optimize stack for threadless operation (warning: single- or multi-threaded server will not work!)" OFF)
set(CONFIG_MMS_SERVER_MAX_GET_FILE_TASKS 5 CACHE STRING "Configure the maximum number of get file tasks")
set(CONFIG_MMS_MAX_NUMBER_OF_DATA_SET_MEMBERS 100 CACHE STRING "Configure the maximum number of dataSet members")
option(CONFIG_ACTIVATE_TCP_KEEPALIVE "Activate TCP keepalive" ON)
option(CONFIG_INCLUDE_GOOSE_SUPPORT "Build with GOOSE support" ON)
option(CONFIG_USE_EXTERNAL_MBEDTLS_DYNLIB "Build with pre-compiled mbedtls dynamic library" OFF)
set(CONFIG_EXTERNAL_MBEDTLS_DYNLIB_PATH "${CMAKE_CURRENT_LIST_DIR}/third_party/mbedtls/mbedtls-2.28/library" CACHE STRING "Path to search for the mbedtls dynamic libraries" )
set(CONFIG_EXTERNAL_MBEDTLS_INCLUDE_PATH "${CMAKE_CURRENT_LIST_DIR}/third_party/mbedtls/mbedtls-2.28/include" CACHE STRING "Path to search for the mbedtls include files" )
# choose the library features which shall be included
option(CONFIG_IEC61850_CONTROL_SERVICE "Build with support for IEC 61850 control features" ON)
option(CONFIG_IEC61850_REPORT_SERVICE "Build with support for IEC 61850 reporting services" ON)
option(CONFIG_IEC61850_LOG_SERVICE "Build with support for IEC 61850 logging services" ON)
option(CONFIG_IEC61850_SERVICE_TRACKING "Build with support for IEC 61850 service tracking" ON)
option(CONFIG_IEC61850_SETTING_GROUPS "Build with support for IEC 61850 setting group services" ON)
option(CONFIG_IEC61850_SUPPORT_USER_READ_ACCESS_CONTROL "Allow user provided callback to control read access" ON)
option(CONFIG_IEC61850_RCB_ALLOW_ONLY_PRECONFIGURED_CLIENT "allow only configured clients (when pre-configured by ClientLN)" OFF)
set(CONFIG_IEC61850_SG_RESVTMS 300 CACHE STRING "Configure the maximum number of SG RESVTMS")
set(CONFIG_REPORTING_DEFAULT_REPORT_BUFFER_SIZE "8000" CACHE STRING "Default buffer size for buffered reports in byte" )
set(CONFIG_REPORTING_DEFAULT_REPORT_BUFFER_SIZE "65536" CACHE STRING "Default buffer size for buffered reports in byte" )
# advanced options
option(DEBUG "Enable debugging mode (include assertions)" OFF)
@ -60,22 +72,6 @@ option(DEBUG_SV_SUBSCRIBER "Enable Sampled Values subscriber debugging" ${DEBUG}
option(DEBUG_SV_PUBLISHER "Enable Sampled Values publisher debugging" ${DEBUG})
option(DEBUG_HAL_ETHERNET "Enable Ethernet HAL printf debugging" ${DEBUG})
#mark_as_advanced(
# DEBUG_SOCKET
# DEBUG_COTP
# DEBUG_ISO_SERVER
# DEBUG_ISO_CLIENT
# DEBUG_IED_SERVER
# DEBUG_IED_CLIENT
# DEBUG_MMS_SERVER
# DEBUG_MMS_CLIENT
# DEBUG_GOOSE_SUBSCRIBER
# DEBUG_GOOSE_PUBLISHER
# DEBUG_SV_SUBSCRIBER
# DEBUG_SV_PUBLISHER
# DEBUG_HAL_ETHERNET
#)
include_directories(
${CMAKE_CURRENT_BINARY_DIR}/config
${CMAKE_CURRENT_LIST_DIR}/src/common/inc
@ -88,21 +84,18 @@ include_directories(
${CMAKE_CURRENT_LIST_DIR}/src/mms/inc_private
${CMAKE_CURRENT_LIST_DIR}/src/mms/iso_mms/asn1c
${CMAKE_CURRENT_LIST_DIR}/src/logging
${CMAKE_CURRENT_LIST_DIR}/src/tls
)
set(API_HEADERS
src/hal/inc/hal_time.h
src/hal/inc/hal_thread.h
src/hal/inc/hal_filesystem.h
src/hal/inc/hal_ethernet.h
src/hal/inc/platform_endian.h
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/libiec61850_platform_includes.h
src/common/inc/linked_list.h
src/common/inc/byte_buffer.h
src/common/inc/lib_memory.h
src/common/inc/string_utilities.h
src/iec61850/inc/iec61850_client.h
src/iec61850/inc/iec61850_common.h
src/iec61850/inc/iec61850_server.h
@ -113,54 +106,64 @@ set(API_HEADERS
src/mms/inc/mms_value.h
src/mms/inc/mms_common.h
src/mms/inc/mms_types.h
src/mms/inc/mms_device_model.h
src/mms/inc/mms_server.h
src/mms/inc/mms_named_variable_list.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/mms/inc/iso_server.h
src/mms/inc/ber_integer.h
src/mms/inc/asn1_ber_primitive_value.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/logging/logging_api.h
src/tls/tls_api.h
${CMAKE_CURRENT_BINARY_DIR}/config/stack_config.h
)
if(MSVC)
if(MSVC AND MSVC_VERSION LESS 1800)
include_directories(
${CMAKE_CURRENT_LIST_DIR}/src/vs
)
endif(MSVC)
endif(MSVC AND MSVC_VERSION LESS 1800)
if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/third_party/mbedtls/mbedtls-2.6.0)
if(CONFIG_USE_EXTERNAL_MBEDTLS_DYNLIB)
set(WITH_MBEDTLS 1)
endif(EXISTS ${CMAKE_CURRENT_LIST_DIR}/third_party/mbedtls/mbedtls-2.6.0)
set(USE_PREBUILD_MBEDTLS 1)
set(MBEDTLS_INCLUDE_DIR ${CONFIG_EXTERNAL_MBEDTLS_INCLUDE_PATH})
endif(CONFIG_USE_EXTERNAL_MBEDTLS_DYNLIB)
if(WITH_MBEDTLS)
include_directories(
${CMAKE_CURRENT_LIST_DIR}/src/tls/mbedtls
${CMAKE_CURRENT_LIST_DIR}/third_party/mbedtls/mbedtls-2.6.0/include
)
if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/third_party/mbedtls/mbedtls-2.28)
set(WITH_MBEDTLS 1)
set(MBEDTLS_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/third_party/mbedtls/mbedtls-2.28/include")
endif(EXISTS ${CMAKE_CURRENT_LIST_DIR}/third_party/mbedtls/mbedtls-2.28)
file(GLOB tls_SRCS ${CMAKE_CURRENT_LIST_DIR}/third_party/mbedtls/mbedtls-2.6.0/library/*.c)
if(WITH_MBEDTLS)
add_definitions(-DCONFIG_MMS_SUPPORT_TLS=1)
add_definitions(-DMBEDTLS_CONFIG_FILE="mbedtls_config.h")
endif(WITH_MBEDTLS)
include(CheckCCompilerFlag)
check_c_compiler_flag("-Wredundant-decls" SUPPORT_REDUNDANT_DECLS)
if (SUPPORT_REDUNDANT_DECLS)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wredundant-decls")
endif(SUPPORT_REDUNDANT_DECLS)
# write the detected stuff to this file
configure_file(
${CMAKE_CURRENT_LIST_DIR}/config/stack_config.h.cmake
${CMAKE_CURRENT_BINARY_DIR}/config/stack_config.h
)
include_directories(
${CMAKE_CURRENT_LIST_DIR}/hal/inc
)
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/hal")
if(DEBUG)
set(CMAKE_BUILD_TYPE Debug)
endif(DEBUG)
if(BUILD_EXAMPLES)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/examples)
endif(BUILD_EXAMPLES)
@ -191,3 +194,5 @@ if(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake")
include(CPack)
endif(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake")

@ -31,30 +31,42 @@ LIB_SOURCE_DIRS += src/iec61850/server/model
LIB_SOURCE_DIRS += src/iec61850/server/mms_mapping
LIB_SOURCE_DIRS += src/iec61850/server/impl
ifeq ($(HAL_IMPL), WIN32)
LIB_SOURCE_DIRS += src/hal/socket/win32
LIB_SOURCE_DIRS += src/hal/thread/win32
LIB_SOURCE_DIRS += src/hal/ethernet/win32
LIB_SOURCE_DIRS += src/hal/filesystem/win32
LIB_SOURCE_DIRS += src/hal/time/win32
LIB_SOURCE_DIRS += hal/socket/win32
LIB_SOURCE_DIRS += hal/thread/win32
LIB_SOURCE_DIRS += hal/ethernet/win32
LIB_SOURCE_DIRS += hal/filesystem/win32
LIB_SOURCE_DIRS += hal/time/win32
LIB_SOURCE_DIRS += hal/serial/win32
LIB_SOURCE_DIRS += hal/memory
else ifeq ($(HAL_IMPL), POSIX)
LIB_SOURCE_DIRS += src/hal/socket/linux
LIB_SOURCE_DIRS += src/hal/thread/linux
LIB_SOURCE_DIRS += src/hal/ethernet/linux
LIB_SOURCE_DIRS += src/hal/filesystem/linux
LIB_SOURCE_DIRS += src/hal/time/unix
LIB_SOURCE_DIRS += hal/socket/linux
LIB_SOURCE_DIRS += hal/thread/linux
LIB_SOURCE_DIRS += hal/ethernet/linux
LIB_SOURCE_DIRS += hal/filesystem/linux
LIB_SOURCE_DIRS += hal/time/unix
LIB_SOURCE_DIRS += hal/serial/linux
LIB_SOURCE_DIRS += hal/memory
else ifeq ($(HAL_IMPL), BSD)
LIB_SOURCE_DIRS += src/hal/socket/bsd
LIB_SOURCE_DIRS += src/hal/thread/bsd
LIB_SOURCE_DIRS += src/hal/ethernet/bsd
LIB_SOURCE_DIRS += src/hal/filesystem/linux
LIB_SOURCE_DIRS += src/hal/time/unix
LIB_SOURCE_DIRS += hal/socket/bsd
LIB_SOURCE_DIRS += hal/thread/bsd
LIB_SOURCE_DIRS += hal/ethernet/bsd
LIB_SOURCE_DIRS += hal/filesystem/linux
LIB_SOURCE_DIRS += hal/time/unix
LIB_SOURCE_DIRS += hal/memory
else ifeq ($(HAL_IMPL), MACOS)
LIB_SOURCE_DIRS += hal/socket/bsd
LIB_SOURCE_DIRS += hal/thread/macos
LIB_SOURCE_DIRS += hal/ethernet/bsd
LIB_SOURCE_DIRS += hal/filesystem/linux
LIB_SOURCE_DIRS += hal/time/unix
LIB_SOURCE_DIRS += hal/memory
endif
LIB_INCLUDE_DIRS += config
LIB_INCLUDE_DIRS += hal/inc
LIB_INCLUDE_DIRS += src/common/inc
LIB_INCLUDE_DIRS += src/mms/iso_mms/asn1c
LIB_INCLUDE_DIRS += src/mms/inc
LIB_INCLUDE_DIRS += src/mms/inc_private
LIB_INCLUDE_DIRS += src/hal/inc
LIB_INCLUDE_DIRS += src/goose
LIB_INCLUDE_DIRS += src/sampled_values
LIB_INCLUDE_DIRS += src/iec61850/inc
@ -66,10 +78,10 @@ LIB_INCLUDE_DIRS += third_party/winpcap/Include
endif
ifdef WITH_MBEDTLS
LIB_SOURCE_DIRS += third_party/mbedtls/mbedtls-2.6.0/library
LIB_SOURCE_DIRS += src/tls/mbedtls
LIB_INCLUDE_DIRS += third_party/mbedtls/mbedtls-2.6.0/include
LIB_INCLUDE_DIRS += src/tls/mbedtls
LIB_SOURCE_DIRS += third_party/mbedtls/mbedtls-2.28/library
LIB_SOURCE_DIRS += hal/tls/mbedtls
LIB_INCLUDE_DIRS += third_party/mbedtls/mbedtls-2.28/include
LIB_INCLUDE_DIRS += hal/tls/mbedtls
CFLAGS += -D'MBEDTLS_CONFIG_FILE="mbedtls_config.h"'
CFLAGS += -D'CONFIG_MMS_SUPPORT_TLS=1'
endif
@ -80,13 +92,14 @@ ifndef INSTALL_PREFIX
INSTALL_PREFIX = ./.install
endif
LIB_API_HEADER_FILES = src/hal/inc/hal_time.h
LIB_API_HEADER_FILES += src/hal/inc/hal_thread.h
LIB_API_HEADER_FILES += src/hal/inc/hal_filesystem.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/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 += src/common/inc/libiec61850_common_api.h
LIB_API_HEADER_FILES += src/common/inc/linked_list.h
LIB_API_HEADER_FILES += src/common/inc/byte_buffer.h
LIB_API_HEADER_FILES += src/common/inc/lib_memory.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
@ -97,22 +110,16 @@ LIB_API_HEADER_FILES += src/iec61850/inc/iec61850_config_file_parser.h
LIB_API_HEADER_FILES += src/mms/inc/mms_value.h
LIB_API_HEADER_FILES += src/mms/inc/mms_common.h
LIB_API_HEADER_FILES += src/mms/inc/mms_types.h
LIB_API_HEADER_FILES += src/mms/inc/mms_device_model.h
LIB_API_HEADER_FILES += src/mms/inc/mms_server.h
LIB_API_HEADER_FILES += src/mms/inc/mms_named_variable_list.h
LIB_API_HEADER_FILES += src/mms/inc/mms_type_spec.h
LIB_API_HEADER_FILES += src/mms/inc/mms_client_connection.h
LIB_API_HEADER_FILES += src/mms/inc/mms_server.h
LIB_API_HEADER_FILES += src/mms/inc/iso_connection_parameters.h
LIB_API_HEADER_FILES += src/mms/inc/iso_server.h
LIB_API_HEADER_FILES += src/mms/inc/ber_integer.h
LIB_API_HEADER_FILES += src/mms/inc/asn1_ber_primitive_value.h
LIB_API_HEADER_FILES += src/goose/goose_subscriber.h
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/tls/tls_api.h
get_sources_from_directory = $(wildcard $1/*.c)
get_sources = $(foreach dir, $1, $(call get_sources_from_directory,$(dir)))
@ -123,7 +130,7 @@ LIB_SOURCES = $(call get_sources,$(LIB_SOURCE_DIRS))
LIB_OBJS = $(call src_to,.o,$(LIB_SOURCES))
CFLAGS += -std=gnu99
#CFLAGS += -Wno-error=format
CFLAGS += -Wno-error=format
CFLAGS += -Wstrict-prototypes
ifneq ($(HAL_IMPL), WIN32)
@ -136,6 +143,9 @@ CFLAGS += -Wnested-externs
CFLAGS += -Wmissing-declarations
CFLAGS += -Wshadow
CFLAGS += -Wall
CFLAGS += -Wextra
CFLAGS += -Wno-format
#CFLAGS += -Wconditional-uninitialized
#CFLAGS += -Werror
all: lib

@ -2,24 +2,31 @@
[![Build Status](https://travis-ci.org/mz-automation/libiec61850.svg?branch=master)](https://travis-ci.org/mz-automation/libiec61850)
This file is part of the documentation of **libIEC61850**. More documentation can be found online at http://libiec61850.com or in the provided doxygen documentation. Also consider to review the examples to understand how to use the library
This file is part of the documentation of **libIEC61850**. More documentation can be found online at http://libiec61850.com.
Content:
The API documentation can be found here:
* C API: https://support.mz-automation.de/doc/libiec61850/c/latest/
* .NET API: https://support.mz-automation.de/doc/libiec61850/net/latest/
* Overview
* Building and running the examples
* Installing the library and the API headers
* Building on Windows with GOOSE support
* Building with the cmake build script
* Using the log service with sqlite
* C# API
* Licensing
* Contributing
* Third-party contributions
Also consider to review the examples to understand how to use the library.
Content:
## Overview
* [Overview](#overview)
* [Features](#features)
* [Examples](#examples)
* [Building and running the examples](#building-and-running-the-examples-with-the-provided-makefiles)
* [Building the library with TLS support](#building-the-library-with-tls-support)
* [Installing the library and the API headers](#installing-the-library-and-the-api-headers)
* [Building on Windows with GOOSE support](#building-on-windows-with-goose-support)
* [Building with the cmake build script](#building-with-the-cmake-build-script)
* [Using the log service with sqlite](#using-the-log-service-with-sqlite)
* [C# API](#c-api)
* [Experimental Python bindings](#experimental-python-bindings)
* [Licensing](#commercial-licenses-and-support)
* [Contributing](#contributing)
## Overview
libiec61850 is an open-source (GPLv3) implementation of an IEC 61850 client and server library implementing the protocols MMS, GOOSE and SV. It is implemented in C (according to the C99 standard) to provide maximum portability. It can be used to implement IEC 61850 compliant client and server applications on embedded systems and PCs running Linux, Windows, and MacOS. Included is a set of simple example applications that can be used as a starting point to implement own IEC 61850 compliant devices or to communicate with IEC 61850 devices. The library has been successfully used in many commercial software products and devices.
@ -44,11 +51,18 @@ The library support the following IEC 61850 protocol features:
* MMS file services (browse, get file, set file, delete/rename file)
** required to download COMTRADE files
* Setting group handling
* Support for service tracking
* GOOSE and SV control block handling
* TLS support
* C and C#/.NET API
## Examples
The examples are built automatically when CMake is used to build the library.
NOTE: Most examples are intended to show a specific function of the library. They are designed to show this function as simple as possible and may miss error handling that has to be present in real applications!
## Building and running the examples with the provided makefiles
In the project root directory type
@ -72,13 +86,17 @@ You can test the server examples by using a generic client or the provided clien
## Building the library with TLS support
Download, unpack, and copy mbedtls-2.6.0 into the third_party/mbedtls folder.
Download, unpack, and copy mbedtls-2.28 into the third_party/mbedtls folder.
NOTE: The current version support mbedtls version 2.28. When you download the source archive from https://tls.mbed.org/ you have to rename the extracted folder to "mbedtls-2.28".
In the main libiec61850 folder run
```
make WITH_MBEDTLS=1
```
```
When using CMake the library is built automatically with TLS support when the folder third_party/mbedtls/mbedtls-2.28 is present.
## Installing the library and the API headers
@ -126,6 +144,16 @@ Depending on the system you don't have to provide a generator to the cmake comma
To select some configuration options you can use ccmake or cmake-gui.
For newer version of Visual Studio you can use one of the following commands (for 64 bit builds):
For Visual Studio 2017:
cmake -G "Visual Studio 15 2017 Win64" ..
For Visual Studio 2019 (new way to specify the x64 platform):
cmake -G "Visual Studio 16 2019" .. -A x64
## Using the log service with sqlite
@ -148,6 +176,8 @@ The experimental Python binding can be created using SWIG with cmake.
To enable the bindings you have to select the phyton configuration option with ccmake of cmake-gui.
We don't provide any support for the Python bindings!
## Commercial licenses and support
Support and commercial license options are provided by MZ Automation GmbH. Please contact info@mz-automation.de for more details.
@ -156,10 +186,4 @@ Support and commercial license options are provided by MZ Automation GmbH. Pleas
If you want to contribute to the improvement and development of the library please send me comments, feature requests, bug reports, or patches. For more than trivial contributions I require you to sign a Contributor License Agreement. Please contact info@libiec61850.com.
## Third-party contributions
- The Mac OS X socket and ethernet layer has been kindly contributed by Michael Clausen, HES-SO Valais-Wallis, http://www.hevs.ch
Please don't send pull requests before signing the Contributor License Agreement! Such pull requests may be silently ignored.

@ -0,0 +1,5 @@
# Security Policy
## Reporting a Vulnerability
Please report security issues to `info@libiec61850.com`

@ -28,7 +28,7 @@
#define DEBUG_HAL_ETHERNET 0
/* Maximum MMS PDU SIZE - default is 65000 */
#define CONFIG_MMS_MAXIMUM_PDU_SIZE 120000
#define CONFIG_MMS_MAXIMUM_PDU_SIZE 65000
/*
* Enable single threaded mode
@ -39,6 +39,10 @@
*/
#define CONFIG_MMS_SINGLE_THREADED 0
#if (WITH_MBEDTLS == 1)
#define CONFIG_MMS_SUPPORT_TLS 1
#endif
/*
* Optimize stack for threadless operation - don't use semaphores
*
@ -47,7 +51,7 @@
#define CONFIG_MMS_THREADLESS_STACK 0
/* number of concurrent MMS client connections the server accepts, -1 for no limit */
#define CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS 5
#define CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS 100
/* activate TCP keep alive mechanism. 1 -> activate */
#define CONFIG_ACTIVATE_TCP_KEEPALIVE 1
@ -64,13 +68,10 @@
/* maximum COTP (ISO 8073) TPDU size - valid range is 1024 - 8192 */
#define CONFIG_COTP_MAX_TPDU_SIZE 8192
/* timeout while reading from TCP stream in ms */
#define CONFIG_TCP_READ_TIMEOUT_MS 1000
/* Ethernet interface ID for GOOSE and SV */
#define CONFIG_ETHERNET_INTERFACE_ID "eth0"
//#define CONFIG_ETHERNET_INTERFACE_ID "vboxnet0"
//#define CONFIG_ETHERNET_INTERFACE_ID "en0" // OS X uses enX in place of ethX as ethernet NIC names.
/* #define CONFIG_ETHERNET_INTERFACE_ID "vboxnet0" */
/* #define CONFIG_ETHERNET_INTERFACE_ID "en0" // OS X uses enX in place of ethX as ethernet NIC names. */
/* Set to 1 to include GOOSE support in the build. Otherwise set to 0 */
#define CONFIG_INCLUDE_GOOSE_SUPPORT 1
@ -143,7 +144,10 @@
#define CONFIG_IEC61850_REPORT_SERVICE 1
/* support buffered report control blocks with ResvTms field */
#define CONFIG_IEC61850_BRCB_WITH_RESVTMS 0
#define CONFIG_IEC61850_BRCB_WITH_RESVTMS 1
/* allow only configured clients (when pre-configured by ClientLN) - note behavior in PIXIT Rp13 */
#define CONFIG_IEC61850_RCB_ALLOW_ONLY_PRECONFIGURED_CLIENT 0
/* The default buffer size of buffered RCBs in bytes */
#define CONFIG_REPORTING_DEFAULT_REPORT_BUFFER_SIZE 65536
@ -157,13 +161,22 @@
/* include support for IEC 61850 log services */
#define CONFIG_IEC61850_LOG_SERVICE 1
/* include support for IEC 61850 service tracking */
#define CONFIG_IEC61850_SERVICE_TRACKING 1
/* allow user to control read access by callback */
#define CONFIG_IEC61850_SUPPORT_USER_READ_ACCESS_CONTROL 1
/* allow application to set server identity (for MMS identity service) at runtime */
#define CONFIG_IEC61850_SUPPORT_SERVER_IDENTITY 1
/* Force memory alignment - required for some platforms (required more memory for buffered reporting) */
#define CONFIG_IEC61850_FORCE_MEMORY_ALIGNMENT 1
/* overwrite default results for MMS identify service */
//#define CONFIG_DEFAULT_MMS_VENDOR_NAME "libiec61850.com"
//#define CONFIG_DEFAULT_MMS_MODEL_NAME "LIBIEC61850"
//#define CONFIG_DEFAULT_MMS_REVISION "1.0.0"
/* #define CONFIG_DEFAULT_MMS_VENDOR_NAME "libiec61850.com" */
/* #define CONFIG_DEFAULT_MMS_MODEL_NAME "LIBIEC61850" */
/* #define CONFIG_DEFAULT_MMS_REVISION "1.0.0" */
/* MMS virtual file store base path - where MMS file services are looking for files */
#define CONFIG_VIRTUAL_FILESTORE_BASEPATH "./vmd-filestore/"
@ -201,20 +214,15 @@
#define MMS_STATUS_SERVICE 1
#define MMS_IDENTIFY_SERVICE 1
#define MMS_FILE_SERVICE 1
#define MMS_OBTAIN_FILE_SERVICE 1
#define MMS_OBTAIN_FILE_SERVICE 1 /* requires MMS_FILE_SERVICE */
#define MMS_DELETE_FILE_SERVICE 1 /* requires MMS_FILE_SERVICE */
#define MMS_RENAME_FILE_SERVICE 0 /* requires MMS_FILE_SERVICE */
#endif /* MMS_DEFAULT_PROFILE */
#if (MMS_WRITE_SERVICE != 1)
#undef CONFIG_IEC61850_CONTROL_SERVICE
#define CONFIG_IEC61850_CONTROL_SERVICE 0
#endif
/* support flat named variable name space required by IEC 61850-8-1 MMS mapping */
#define CONFIG_MMS_SUPPORT_FLATTED_NAME_SPACE 1
/* VMD scope named variables are not used by IEC 61850 (one application is ICCP) */
#define CONFIG_MMS_SUPPORT_VMD_SCOPE_NAMED_VARIABLES 0
/* Sort getNameList response according to the MMS specified collation order - this is required by the standard
* Set to 0 only for performance reasons and when no certification is required! */
#define CONFIG_MMS_SORT_NAME_LIST 1
@ -227,9 +235,61 @@
/* Support user access to raw messages */
#define CONFIG_MMS_RAW_MESSAGE_LOGGING 1
/* Allow to set the virtual filestore basepath for MMS file services at runtime with the
* MmsServer_setFilestoreBasepath function
/* Allow to set the virtual file store base path for MMS file services at runtime with the
* MmsServer_setFilestoreBasepath function.
*/
#define CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME 1
/* enable to configure MmsServer at runtime */
#define CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME 1
/* Define the default number of the maximum outstanding calls allowed by the caller (client) */
#define CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLING 5
/* Define the default number of the maximum outstanding calls allowed by the calling endpoint (server) */
#define CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLED 5
/************************************************************************************
* Check configuration for consistency - DO NOT MODIFY THIS PART!
************************************************************************************/
#if (CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLING < 1)
#error "Invalid configuration: CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLING must be greater than 0!"
#endif
#if (CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLED < 1)
#error "Invalid configuration: CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLED must be greater than 0!"
#endif
#if (MMS_JOURNAL_SERVICE != 1)
#if (CONFIG_IEC61850_LOG_SERVICE == 1)
#warning "Invalid configuration: CONFIG_IEC61850_LOG_SERVICE requires MMS_JOURNAL_SERVICE!"
#endif
#undef CONFIG_IEC61850_LOG_SERVICE
#define CONFIG_IEC61850_LOG_SERVICE 0
#endif
#if (MMS_WRITE_SERVICE != 1)
#if (CONFIG_IEC61850_CONTROL_SERVICE == 1)
#warning "Invalid configuration: CONFIG_IEC61850_CONTROL_SERVICE requires MMS_WRITE_SERVICE!"
#endif
#undef CONFIG_IEC61850_CONTROL_SERVICE
#define CONFIG_IEC61850_CONTROL_SERVICE 0
#endif
#if (MMS_FILE_SERVICE != 1)
#if (MMS_OBTAIN_FILE_SERVICE == 1)
#warning "Invalid configuration: MMS_OBTAIN_FILE_SERVICE requires MMS_FILE_SERVICE!"
#endif
#undef MMS_OBTAIN_FILE_SERVICE
#define MMS_OBTAIN_FILE_SERVICE 0
#endif
#endif /* STACK_CONFIG_H_ */

@ -63,13 +63,10 @@
/* maximum COTP (ISO 8073) TPDU size - valid range is 1024 - 8192 */
#define CONFIG_COTP_MAX_TPDU_SIZE 8192
/* timeout while reading from TCP stream in ms */
#define CONFIG_TCP_READ_TIMEOUT_MS 1000
/* Ethernet interface ID for GOOSE and SV */
#define CONFIG_ETHERNET_INTERFACE_ID "eth0"
//#define CONFIG_ETHERNET_INTERFACE_ID "vboxnet0"
//#define CONFIG_ETHERNET_INTERFACE_ID "en0" // OS X uses enX in place of ethX as ethernet NIC names.
/* #define CONFIG_ETHERNET_INTERFACE_ID "vboxnet0" */
/* #define CONFIG_ETHERNET_INTERFACE_ID "en0" // OS X uses enX in place of ethX as ethernet NIC names. */
/* Set to 1 to include GOOSE support in the build. Otherwise set to 0 */
#cmakedefine01 CONFIG_INCLUDE_GOOSE_SUPPORT
@ -137,7 +134,10 @@
#cmakedefine01 CONFIG_IEC61850_REPORT_SERVICE
/* support buffered report control blocks with ResvTms field */
#define CONFIG_IEC61850_BRCB_WITH_RESVTMS 0
#define CONFIG_IEC61850_BRCB_WITH_RESVTMS 1
/* allow only configured clients (when pre-configured by ClientLN) - note behavior in PIXIT Rp13 */
#cmakedefine01 CONFIG_IEC61850_RCB_ALLOW_ONLY_PRECONFIGURED_CLIENT
/* The default buffer size of buffered RCBs in bytes */
#cmakedefine CONFIG_REPORTING_DEFAULT_REPORT_BUFFER_SIZE @CONFIG_REPORTING_DEFAULT_REPORT_BUFFER_SIZE@
@ -146,11 +146,20 @@
#cmakedefine01 CONFIG_IEC61850_SETTING_GROUPS
/* default reservation time of a setting group control block in s */
#define CONFIG_IEC61850_SG_RESVTMS 100
#cmakedefine CONFIG_IEC61850_SG_RESVTMS @CONFIG_IEC61850_SG_RESVTMS@
/* include support for IEC 61850 log services */
#cmakedefine01 CONFIG_IEC61850_LOG_SERVICE
/* include support for IEC 61850 service tracking */
#cmakedefine01 CONFIG_IEC61850_SERVICE_TRACKING
/* allow user to control read access by callback */
#cmakedefine01 CONFIG_IEC61850_SUPPORT_USER_READ_ACCESS_CONTROL
/* allow application to set server identity (for MMS identity service) at runtime */
#define CONFIG_IEC61850_SUPPORT_SERVER_IDENTITY 1
/* Force memory alignment - required for some platforms (required more memory for buffered reporting) */
#define CONFIG_IEC61850_FORCE_MEMORY_ALIGNMENT 1
@ -178,7 +187,10 @@
#define CONFIG_MMS_MAX_NUMBER_OF_VMD_SPECIFIC_DATA_SETS 10
/* Maximum number of the members in a data set (named variable list) */
#define CONFIG_MMS_MAX_NUMBER_OF_DATA_SET_MEMBERS 50
#cmakedefine CONFIG_MMS_MAX_NUMBER_OF_DATA_SET_MEMBERS @CONFIG_MMS_MAX_NUMBER_OF_DATA_SET_MEMBERS@
/* Maximum number of get file tasks */
#cmakedefine CONFIG_MMS_SERVER_MAX_GET_FILE_TASKS @CONFIG_MMS_SERVER_MAX_GET_FILE_TASKS@
/* Definition of supported services */
#define MMS_DEFAULT_PROFILE 1
@ -196,13 +208,10 @@
#define MMS_IDENTIFY_SERVICE 1
#define MMS_FILE_SERVICE 1
#define MMS_OBTAIN_FILE_SERVICE 1
#define MMS_DELETE_FILE_SERVICE 1
#define MMS_RENAME_FILE_SERVICE 0
#endif /* MMS_DEFAULT_PROFILE */
#if (MMS_WRITE_SERVICE != 1)
#undef CONFIG_IEC61850_CONTROL_SERVICE
#define CONFIG_IEC61850_CONTROL_SERVICE 0
#endif
/* Sort getNameList response according to the MMS specified collation order - this is required by the standard
* Set to 0 only for performance reasons and when no certification is required! */
#define CONFIG_MMS_SORT_NAME_LIST 1
@ -220,4 +229,56 @@
*/
#define CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME 1
/* enable to configure MmsServer at runtime */
#define CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME 1
/* Define the default number of the maximum outstanding calls allowed by the caller (client) */
#define CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLING 5
/* Define the default number of the maximum outstanding calls allowed by the calling endpoint (server) */
#define CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLED 5
/************************************************************************************
* Check configuration for consistency - DO NOT MODIFY THIS PART!
************************************************************************************/
#if (CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLING < 1)
#error "Invalid configuration: CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLING must be greater than 0!"
#endif
#if (CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLED < 1)
#error "Invalid configuration: CONFIG_DEFAULT_MAX_SERV_OUTSTANDING_CALLED must be greater than 0!"
#endif
#if (MMS_JOURNAL_SERVICE != 1)
#if (CONFIG_IEC61850_LOG_SERVICE == 1)
#warning "Invalid configuration: CONFIG_IEC61850_LOG_SERVICE requires MMS_JOURNAL_SERVICE!"
#endif
#undef CONFIG_IEC61850_LOG_SERVICE
#define CONFIG_IEC61850_LOG_SERVICE 0
#endif
#if (MMS_WRITE_SERVICE != 1)
#if (CONFIG_IEC61850_CONTROL_SERVICE == 1)
#warning "Invalid configuration: CONFIG_IEC61850_CONTROL_SERVICE requires MMS_WRITE_SERVICE!"
#endif
#undef CONFIG_IEC61850_CONTROL_SERVICE
#define CONFIG_IEC61850_CONTROL_SERVICE 0
#endif
#if (MMS_FILE_SERVICE != 1)
#if (MMS_OBTAIN_FILE_SERVICE == 1)
#warning "Invalid configuration: MMS_OBTAIN_FILE_SERVICE requires MMS_FILE_SERVICE!"
#endif
#undef MMS_OBTAIN_FILE_SERVICE
#define MMS_OBTAIN_FILE_SERVICE 0
#endif
#endif /* STACK_CONFIG_H_ */

@ -54,7 +54,7 @@ connectionIndicationHandler(IedServer server, ClientConnection connection, bool
}
static CheckHandlerResult
performCheckHandler(void* parameter, MmsValue* ctlVal, bool test, bool interlockCheck, ClientConnection connection)
performCheckHandler(ControlAction action, void* parameter, MmsValue* ctlVal, bool test, bool interlockCheck, ClientConnection connection)
{
if (controllingClient == NULL) {
printf("Client takes control -> switch to remote control operation mode\n");
@ -101,7 +101,7 @@ updateLED3stVal(bool newLedState, uint64_t timeStamp) {
}
static ControlHandlerResult
controlHandlerForBinaryOutput(void* parameter, MmsValue* value, bool test)
controlHandlerForBinaryOutput(ControlAction action, void* parameter, MmsValue* value, bool test)
{
if (test)
return CONTROL_RESULT_OK;
@ -151,7 +151,7 @@ static int ledOffTimeMs = 1000;
static int32_t opCnt = 0;
static ControlHandlerResult
controlHandlerForInt32Controls(void* parameter, MmsValue* value, bool test)
controlHandlerForInt32Controls(ControlAction action, void* parameter, MmsValue* value, bool test)
{
if (test)
return CONTROL_RESULT_OK;

@ -270,7 +270,7 @@
</DOType>
<DOType cdc="SPG" id="SPG_0">
<DA name="setVal" bType="BOOLEAN" fc="SG" dchg="true" />
<DA name="setVal" bType="BOOLEAN" fc="SP" dchg="true" />
</DOType>
<DOType cdc="TSG" id="TSG_0">

@ -18,7 +18,7 @@ extern DataSetEntry iedModelds_GenericIO_LLN0_Events_fcda3;
DataSetEntry iedModelds_GenericIO_LLN0_Events_fcda0 = {
"GenericIO",
false,
"GGIO1$ST$SPCSO1$stVal",
"GGIO1$ST$SPCSO1$stVal",
-1,
NULL,
NULL,
@ -28,7 +28,7 @@ DataSetEntry iedModelds_GenericIO_LLN0_Events_fcda0 = {
DataSetEntry iedModelds_GenericIO_LLN0_Events_fcda1 = {
"GenericIO",
false,
"GGIO1$ST$SPCSO2$stVal",
"GGIO1$ST$SPCSO2$stVal",
-1,
NULL,
NULL,
@ -38,7 +38,7 @@ DataSetEntry iedModelds_GenericIO_LLN0_Events_fcda1 = {
DataSetEntry iedModelds_GenericIO_LLN0_Events_fcda2 = {
"GenericIO",
false,
"GGIO1$ST$SPCSO3$stVal",
"GGIO1$ST$SPCSO3$stVal",
-1,
NULL,
NULL,
@ -48,7 +48,7 @@ DataSetEntry iedModelds_GenericIO_LLN0_Events_fcda2 = {
DataSetEntry iedModelds_GenericIO_LLN0_Events_fcda3 = {
"GenericIO",
false,
"GGIO1$ST$DPCSO1$stVal",
"GGIO1$ST$DPCSO1$stVal",
-1,
NULL,
NULL,
@ -7570,11 +7570,11 @@ extern ReportControlBlock iedModel_GenericIO_LLN0_report2;
extern ReportControlBlock iedModel_GenericIO_LLN0_report3;
extern ReportControlBlock iedModel_GenericIO_LLN0_report4;
ReportControlBlock iedModel_GenericIO_LLN0_report0 = {&iedModel_GenericIO_LLN0, "EventsRCB01", "Events1", false, "Events", 1, 24, 111, 50, 1000, &iedModel_GenericIO_LLN0_report1};
ReportControlBlock iedModel_GenericIO_LLN0_report1 = {&iedModel_GenericIO_LLN0, "EventsRCB02", "Events1", false, "Events", 1, 24, 111, 50, 1000, &iedModel_GenericIO_LLN0_report2};
ReportControlBlock iedModel_GenericIO_LLN0_report2 = {&iedModel_GenericIO_LLN0, "EventsRCB03", "Events1", false, "Events", 1, 24, 111, 50, 1000, &iedModel_GenericIO_LLN0_report3};
ReportControlBlock iedModel_GenericIO_LLN0_report3 = {&iedModel_GenericIO_LLN0, "EventsRCB04", "Events1", false, "Events", 1, 24, 111, 50, 1000, &iedModel_GenericIO_LLN0_report4};
ReportControlBlock iedModel_GenericIO_LLN0_report4 = {&iedModel_GenericIO_LLN0, "EventsRCB05", "Events1", false, "Events", 1, 24, 111, 50, 1000, NULL};
ReportControlBlock iedModel_GenericIO_LLN0_report0 = {&iedModel_GenericIO_LLN0, "EventsRCB01", "Events1", false, "Events", 1, 88, 239, 50, 1000, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, &iedModel_GenericIO_LLN0_report1};
ReportControlBlock iedModel_GenericIO_LLN0_report1 = {&iedModel_GenericIO_LLN0, "EventsRCB02", "Events1", false, "Events", 1, 88, 239, 50, 1000, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, &iedModel_GenericIO_LLN0_report2};
ReportControlBlock iedModel_GenericIO_LLN0_report2 = {&iedModel_GenericIO_LLN0, "EventsRCB03", "Events1", false, "Events", 1, 88, 239, 50, 1000, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, &iedModel_GenericIO_LLN0_report3};
ReportControlBlock iedModel_GenericIO_LLN0_report3 = {&iedModel_GenericIO_LLN0, "EventsRCB04", "Events1", false, "Events", 1, 88, 239, 50, 1000, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, &iedModel_GenericIO_LLN0_report4};
ReportControlBlock iedModel_GenericIO_LLN0_report4 = {&iedModel_GenericIO_LLN0, "EventsRCB05", "Events1", false, "Events", 1, 88, 239, 50, 1000, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, NULL};

@ -28,10 +28,7 @@ using IEC61850.Common;
namespace IEC61850
{
/// <summary>
/// IEC 61850 common API parts (used by client and server API)
/// </summary>
// IEC 61850 common API parts (used by client and server API)
namespace Common {
/// <summary>
@ -76,8 +73,8 @@ namespace IEC61850
}
}
namespace Client {
namespace Client
{
[StructLayout(LayoutKind.Sequential)]
internal struct LastApplErrorInternal
{
@ -101,6 +98,13 @@ namespace IEC61850
}
}
public enum ControlActionType
{
SELECT = 0,
OPERATE = 1,
CANCEL = 2
}
/// <summary>
/// Control object.
/// </summary>
@ -118,10 +122,40 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern int ControlObjectClient_getControlModel(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[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)]
[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);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
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,
ControlObjectClient_ControlActionHandler handler, IntPtr parameter);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt32 ControlObjectClient_selectAsync(IntPtr self, out int err,
ControlObjectClient_ControlActionHandler handler, IntPtr parameter);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt32 ControlObjectClient_selectWithValueAsync(IntPtr self, out int err, IntPtr ctlVal,
ControlObjectClient_ControlActionHandler handler, IntPtr parameter);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt32 ControlObjectClient_cancelAsync(IntPtr self, out int err,
ControlObjectClient_ControlActionHandler handler, IntPtr parameter);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool ControlObjectClient_select(IntPtr self);
@ -138,13 +172,13 @@ namespace IEC61850
private static extern void ControlObjectClient_setOrigin(IntPtr self, string orIdent, int orCat);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void ControlObjectClient_setInterlockCheck(IntPtr self, bool value);
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, bool value);
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, bool value);
private static extern void ControlObjectClient_setTestMode(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void InternalCommandTerminationHandler(IntPtr parameter,IntPtr controlClient);
@ -156,7 +190,7 @@ namespace IEC61850
public delegate void CommandTerminationHandler (Object parameter, ControlObject controlObject);
private IedConnection iedConnection;
private IntPtr controlObject;
private IntPtr self;
private CommandTerminationHandler commandTerminationHandler = null;
private Object commandTerminationHandlerParameter = null;
@ -173,14 +207,14 @@ namespace IEC61850
{
this.iedConnection = iedConnection;
this.controlObject = ControlObjectClient_create(objectReference, connection);
this.self = ControlObjectClient_create(objectReference, connection);
if (this.controlObject == System.IntPtr.Zero)
if (this.self == System.IntPtr.Zero)
throw new IedConnectionException("Control object not found", 0);
intCommandTerminationHandler = new InternalCommandTerminationHandler (MyCommandTerminationHandler);
ControlObjectClient_setCommandTerminationHandler(controlObject, intCommandTerminationHandler, controlObject);
ControlObjectClient_setCommandTerminationHandler(self, intCommandTerminationHandler, self);
}
/// <summary>
@ -191,11 +225,22 @@ namespace IEC61850
/// </returns>
public ControlModel GetControlModel ()
{
ControlModel controlModel = (ControlModel) ControlObjectClient_getControlModel(controlObject);
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.
/// </summary>
@ -207,7 +252,17 @@ namespace IEC61850
/// </param>
public void SetOrigin (string originator, OrCat originatorCategory)
{
ControlObjectClient_setOrigin(controlObject, 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);
}
}
/// <summary>
@ -297,29 +352,203 @@ namespace IEC61850
/// <returns>true when the operation has been successful, false otherwise</returns>
public bool Operate (MmsValue ctlVal, UInt64 operTime)
{
return ControlObjectClient_operate(controlObject, ctlVal.valueReference, 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)
{
GCHandle handle = GCHandle.FromIntPtr(parameter);
Tuple<ControlActionHandler, object> callbackInfo = handle.Target as Tuple<ControlActionHandler, object>;
ControlActionHandler handler = callbackInfo.Item1;
object handlerParameter = callbackInfo.Item2;
handle.Free();
IedClientError clientError = (IedClientError)err;
handler(invokeId, handlerParameter, clientError, (ControlActionType) type, success);
}
/// <summary>
/// Operate the control with the specified control value.
/// </summary>
/// <param name='ctlVal'>the new value of the control</param>
/// <param name="handler">Callback function to handle the received response or service timeout</param>
/// <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)
{
return OperateAsync (ctlVal, 0, handler, parameter);
}
/// <summary>
/// Operate the control with the specified control value (time activated control).
/// </summary>
/// <param name='ctlVal'>the new value of the control</param>
/// <param name='operTime'>the time when the operation will be executed</param>
/// <param name="handler">Callback function to handle the received response or service timeout</param>
/// <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)
{
MmsValue value = new MmsValue(ctlVal);
return OperateAsync (value, operTime, handler, parameter);
}
/// <summary>
/// Operate the control with the specified control value.
/// </summary>
/// <param name='ctlVal'>the new value of the control</param>
/// <param name="handler">Callback function to handle the received response or service timeout</param>
/// <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)
{
return OperateAsync (ctlVal, 0, handler, parameter);
}
/// <summary>
/// Operate the control with the specified control value (time activated control).
/// </summary>
/// <param name='ctlVal'>the new value of the control</param>
/// <param name='operTime'>the time when the operation will be executed</param>
/// <param name="handler">Callback function to handle the received response or service timeout</param>
/// <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)
{
MmsValue value = new MmsValue(ctlVal);
return OperateAsync (value, operTime, handler, parameter);
}
/// <summary>
/// Operate the control with the specified control value.
/// </summary>
/// <param name='ctlVal'>the new value of the control</param>
/// <param name="handler">Callback function to handle the received response or service timeout</param>
/// <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)
{
return OperateAsync (ctlVal, 0, handler, parameter);
}
/// <summary>
/// Operate the control with the specified control value (time activated control).
/// </summary>
/// <param name='ctlVal'>the new value of the control</param>
/// <param name='operTime'>the time when the operation will be executed</param>
/// <param name="handler">Callback function to handle the received response or service timeout</param>
/// <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)
{
return OperateAsync (ctlVal, operTime, handler, parameter);
}
/// <summary>
/// Operate the control with the specified control value.
/// </summary>
/// <param name='ctlVal'>the new value of the control</param>
/// <param name="handler">Callback function to handle the received response or service timeout</param>
/// <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)
{
return OperateAsync (ctlVal, 0, handler, parameter);
}
/// <summary>
/// Operate the control with the specified control value (time activated control).
/// </summary>
/// <param name='ctlVal'>the new value of the control</param>
/// <param name='operTime'>the time when the operation will be executed</param>
/// <param name="handler">Callback function to handle the received response or service timeout</param>
/// <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)
{
int error;
Tuple<ControlActionHandler, object> callbackInfo = Tuple.Create(handler, parameter);
GCHandle handle = GCHandle.Alloc(callbackInfo);
if (internalOperateHandler == null)
internalOperateHandler = new ControlObjectClient_ControlActionHandler(nativeOperateHandler);
UInt32 invokeId = ControlObjectClient_operateAsync(self, out error, ctlVal.valueReference, operTime, internalOperateHandler, GCHandle.ToIntPtr(handle));
if (error != 0)
{
handle.Free();
throw new IedConnectionException("Operate failed", error);
}
return invokeId;
}
/// <summary>
/// Select the control object.
/// </summary>
/// <returns>true when the selection has been successful, false otherwise</returns>
public bool Select ()
{
return ControlObjectClient_select(controlObject);
return ControlObjectClient_select(self);
}
/// <summary>
/// Select the control object.
/// </summary>
/// <param name="handler">Callback function to handle the received response or service timeout</param>
/// <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 SelectAsync(ControlActionHandler handler, object parameter)
{
int error;
Tuple<ControlActionHandler, object> callbackInfo = Tuple.Create(handler, parameter);
GCHandle handle = GCHandle.Alloc(callbackInfo);
if (internalOperateHandler == null)
internalOperateHandler = new ControlObjectClient_ControlActionHandler(nativeOperateHandler);
UInt32 invokeId = ControlObjectClient_selectAsync(self, out error, internalOperateHandler, GCHandle.ToIntPtr(handle));
if (error != 0)
{
handle.Free();
throw new IedConnectionException("Select failed", error);
}
return invokeId;
}
/// <summary>
/// Send a select with value command for generic MmsValue instances
/// </summary>
/// <param name='ctlVal'>
/// the value to be checked.
/// </param>
/// <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)
{
return ControlObjectClient_selectWithValue(controlObject, ctlVal.valueReference);
return ControlObjectClient_selectWithValue(self, ctlVal.valueReference);
}
/// <summary>
@ -358,13 +587,111 @@ namespace IEC61850
return SelectWithValue(new MmsValue(ctlVal));
}
/// <summary>
/// Send a select with value command for boolean controls - asynchronous version
/// </summary>
/// <param name='ctlVal'>the value to be checked.</param>
/// <param name="handler">Callback function to handle the received response or service timeout</param>
/// <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)
{
return SelectWithValueAsync(new MmsValue(ctlVal), handler, parameter);
}
/// <summary>
/// Send a select with value command for integer controls - asynchronous version
/// </summary>
/// <param name='ctlVal'>the value to be checked.</param>
/// <param name="handler">Callback function to handle the received response or service timeout</param>
/// <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)
{
return SelectWithValueAsync(new MmsValue(ctlVal), handler, parameter);
}
/// <summary>
/// Send a select with value command for float controls - asynchronous version
/// </summary>
/// <param name='ctlVal'>the value to be checked.</param>
/// <param name="handler">Callback function to handle the received response or service timeout</param>
/// <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)
{
return SelectWithValueAsync(new MmsValue(ctlVal), handler, parameter);
}
/// <summary>
/// Send a select with value command for generic MmsValue instances - asynchronous version
/// </summary>
/// <param name='ctlVal'>the value to be checked.</param>
/// <param name="handler">Callback function to handle the received response or service timeout</param>
/// <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)
{
int error;
Tuple<ControlActionHandler, object> callbackInfo = Tuple.Create(handler, parameter);
GCHandle handle = GCHandle.Alloc(callbackInfo);
if (internalOperateHandler == null)
internalOperateHandler = new ControlObjectClient_ControlActionHandler(nativeOperateHandler);
UInt32 invokeId = ControlObjectClient_selectWithValueAsync(self, out error, ctlVal.valueReference, internalOperateHandler, GCHandle.ToIntPtr(handle));
if (error != 0)
{
handle.Free();
throw new IedConnectionException("Select with value failed", error);
}
return invokeId;
}
/// <summary>
/// Cancel a selection or time activated operation
/// </summary>
/// <returns>true when the cancelation has been successful, false otherwise</returns>
/// <param name="handler">Callback function to handle the received response or service timeout</param>
/// <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 ()
{
return ControlObjectClient_cancel(controlObject);
return ControlObjectClient_cancel(self);
}
/// <summary>
/// Cancel a selection or time activated operation
/// </summary>
public UInt32 CancelAsync(ControlActionHandler handler, object parameter)
{
int error;
Tuple<ControlActionHandler, object> callbackInfo = Tuple.Create(handler, parameter);
GCHandle handle = GCHandle.Alloc(callbackInfo);
if (internalOperateHandler == null)
internalOperateHandler = new ControlObjectClient_ControlActionHandler(nativeOperateHandler);
UInt32 invokeId = ControlObjectClient_cancelAsync(self, out error, internalOperateHandler, GCHandle.ToIntPtr(handle));
if (error != 0)
{
handle.Free();
throw new IedConnectionException("Cancel failed", error);
}
return invokeId;
}
/// <summary>
@ -373,7 +700,7 @@ namespace IEC61850
[Obsolete("use SetSynchroCheck instead")]
public void EnableSynchroCheck ()
{
ControlObjectClient_setSynchroCheck (controlObject, true);
ControlObjectClient_setSynchroCheck (self, true);
}
/// <summary>
@ -382,7 +709,7 @@ namespace IEC61850
[Obsolete("use SetInterlockCheck instead")]
public void EnableInterlockCheck ()
{
ControlObjectClient_setInterlockCheck (controlObject, true);
ControlObjectClient_setInterlockCheck (self, true);
}
/// <summary>
@ -390,7 +717,7 @@ namespace IEC61850
/// </summary>
public void SetInterlockCheck (bool value)
{
ControlObjectClient_setInterlockCheck (controlObject, value);
ControlObjectClient_setInterlockCheck (self, value);
}
/// <summary>
@ -398,7 +725,7 @@ namespace IEC61850
/// </summary>
public void SetSynchroCheck (bool value)
{
ControlObjectClient_setSynchroCheck (controlObject, value);
ControlObjectClient_setSynchroCheck (self, value);
}
/// <summary>
@ -406,7 +733,7 @@ namespace IEC61850
/// </summary>
public void SetTestMode (bool value)
{
ControlObjectClient_setTestMode (controlObject, value);
ControlObjectClient_setTestMode (self, value);
}
/// <summary>
@ -417,7 +744,7 @@ namespace IEC61850
/// </returns>
public LastApplError GetLastApplError ()
{
LastApplErrorInternal lastApplError = ControlObjectClient_getLastApplError(controlObject);
LastApplErrorInternal lastApplError = ControlObjectClient_getLastApplError(self);
return new LastApplError(lastApplError);
}
@ -438,9 +765,9 @@ namespace IEC61850
}
protected virtual void Dispose(bool disposing) {
if (this.controlObject != System.IntPtr.Zero) {
ControlObjectClient_destroy (controlObject);
this.controlObject = System.IntPtr.Zero;
if (this.self != System.IntPtr.Zero) {
ControlObjectClient_destroy (self);
this.self = System.IntPtr.Zero;
}
}
@ -448,7 +775,10 @@ namespace IEC61850
Dispose (true);
}
~ControlObject()
{
Dispose (false);
}
}
}

@ -1,7 +1,7 @@
/*
* DataSet.cs
*
* Copyright 2014 Michael Zillgith
* Copyright 2014-2018 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -28,34 +28,39 @@ using IEC61850.Common;
namespace IEC61850
{
namespace Client
{
namespace Client
{
/// <summary>
/// This class is used to represent a data set. It is used to store the values
/// of a data set.
/// </summary>
public class DataSet
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientDataSet_destroy (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientDataSet_getValues (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientDataSet_getReference (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int ClientDataSet_getDataSetSize (IntPtr self);
private IntPtr nativeObject;
private MmsValue values = null;
private string reference = null;
internal DataSet (IntPtr nativeObject)
{
this.nativeObject = nativeObject;
}
/// <remarks>
/// This class manages native resource. Take care that the finalizer/Dispose is not
/// called while running a method or the object is still in use by another object.
/// If in doubt please use the "using" statement.
/// </remarks>
public class DataSet : IDisposable
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientDataSet_destroy(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientDataSet_getValues(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientDataSet_getReference(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int ClientDataSet_getDataSetSize(IntPtr self);
private IntPtr nativeObject;
private MmsValue values = null;
private string reference = null;
internal DataSet(IntPtr nativeObject)
{
this.nativeObject = nativeObject;
}
/// <summary>
/// Gets the object reference of the data set
@ -63,16 +68,17 @@ namespace IEC61850
/// <returns>
/// object reference.
/// </returns>
public string GetReference ()
{
if (reference == null) {
IntPtr nativeString = ClientDataSet_getReference (nativeObject);
public string GetReference()
{
if (reference == null)
{
IntPtr nativeString = ClientDataSet_getReference(nativeObject);
reference = Marshal.PtrToStringAnsi (nativeString);
}
reference = Marshal.PtrToStringAnsi(nativeString);
}
return reference;
}
return reference;
}
/// <summary>
/// Gets the values associated with the data set object
@ -83,16 +89,17 @@ namespace IEC61850
/// <returns>
/// The locally stored values of the data set (as MmsValue instance of type MMS_ARRAY)
/// </returns>
public MmsValue GetValues ()
{
if (values == null) {
IntPtr nativeValues = ClientDataSet_getValues (nativeObject);
public MmsValue GetValues()
{
if (values == null)
{
IntPtr nativeValues = ClientDataSet_getValues(nativeObject);
values = new MmsValue (nativeValues, false);
}
values = new MmsValue(nativeValues, false);
}
return values;
}
return values.Clone();
}
/// <summary>
@ -101,22 +108,47 @@ namespace IEC61850
/// <returns>
/// the number of elementes (data set members)
/// </returns>
public int GetSize ()
{
return ClientDataSet_getDataSetSize (nativeObject);
}
~DataSet ()
{
ClientDataSet_destroy (nativeObject);
}
internal IntPtr getNativeInstance ()
{
return nativeObject;
}
}
}
public int GetSize()
{
return ClientDataSet_getDataSetSize(nativeObject);
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
lock (this)
{
if (!disposed)
{
if (nativeObject != IntPtr.Zero)
{
ClientDataSet_destroy(nativeObject);
nativeObject = IntPtr.Zero;
}
disposed = true;
}
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~DataSet()
{
Dispose(false);
}
internal IntPtr getNativeInstance()
{
return nativeObject;
}
}
}
}

@ -31,7 +31,7 @@ namespace IEC61850
namespace Client
{
public class GooseControlBlock {
public class GooseControlBlock : IDisposable {
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientGooseControlBlock_create (string dataAttributeReference);
@ -43,14 +43,14 @@ namespace IEC61850
static extern IntPtr IedConnection_getGoCBValues (IntPtr connection, out int error, string rcbReference, IntPtr updateRcb);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedConnection_setGoCBValues (IntPtr connection, out int error, IntPtr rcb, UInt32 parametersMask, bool singleRequest);
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, bool rptEna);
static extern void ClientGooseControlBlock_setGoEna(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool rptEna);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientGooseControlBlock_getGoID (IntPtr self);
@ -84,6 +84,18 @@ namespace IEC61850
[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 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_appid(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientGooseControlBlock_setDstAddress (IntPtr self, PhyComAddress value);
@ -232,7 +244,23 @@ namespace IEC61850
public PhyComAddress GetDstAddress()
{
return ClientGooseControlBlock_getDstAddress (self);
PhyComAddress addr = new PhyComAddress();
IntPtr value = ClientGooseControlBlock_getDstAddress_addr(self);
MmsValue mmsValue = new MmsValue(value);
byte[] dstMacAddr = mmsValue.getOctetString();
dstMacAddr.CopyTo(addr.dstAddress, 0);
addr.dstAddress = dstMacAddr;
addr.appId = ClientGooseControlBlock_getDstAddress_appid(self);
addr.vlanId = ClientGooseControlBlock_getDstAddress_vid(self);
addr.vlanPriority = ClientGooseControlBlock_getDstAddress_priority(self);
return addr;
}
public void SetDstAddress(PhyComAddress value)

@ -22,6 +22,7 @@
*/
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using IEC61850.Common;
@ -69,6 +70,8 @@ namespace IEC61850
private bool isDisposed = false;
private List<GooseSubscriber> subscribers = new List<GooseSubscriber>();
public GooseReceiver()
{
self = GooseReceiver_create ();
@ -79,14 +82,29 @@ namespace IEC61850
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)
{
GooseReceiver_addSubscriber (self, subscriber.self);
if (subscriber.attachedToReceiver == false)
{
subscriber.attachedToReceiver = true;
GooseReceiver_addSubscriber(self, subscriber.self);
subscribers.Add(subscriber);
}
}
public void RemoveSubscriber(GooseSubscriber subscriber)
{
GooseReceiver_removeSubscriber (self, subscriber.self);
if (subscriber.attachedToReceiver)
{
GooseReceiver_removeSubscriber(self, subscriber.self);
subscribers.Remove(subscriber);
subscriber.attachedToReceiver = false;
}
}
public void Start()
@ -175,10 +193,22 @@ namespace IEC61850
[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;
@ -214,7 +244,6 @@ namespace IEC61850
return GooseSubscriber_isValid (self);
}
public void SetListener(GooseListener listener, object parameter)
{
this.listener = listener;
@ -227,6 +256,21 @@ namespace IEC61850
}
}
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);
@ -300,12 +344,20 @@ namespace IEC61850
{
if (isDisposed == false) {
isDisposed = true;
GooseSubscriber_destroy (self);
if (attachedToReceiver == false)
GooseSubscriber_destroy (self);
self = IntPtr.Zero;
}
}
}
~GooseSubscriber()
{
Dispose();
}
}
}

@ -7,8 +7,6 @@
<OutputType>Library</OutputType>
<RootNamespace>iec61850dotnet</RootNamespace>
<AssemblyName>iec61850dotnet</AssemblyName>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@ -30,10 +28,6 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="AssemblyInfo.cs" />
@ -52,6 +46,7 @@
<Compile Include="GooseControlBlock.cs" />
<Compile Include="GooseSubscriber.cs" />
<Compile Include="SampledValuesSubscriber.cs" />
<Compile Include="IedServerConfig.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>

File diff suppressed because it is too large Load Diff

@ -29,6 +29,13 @@ namespace IEC61850
namespace Common
{
public enum Iec61850Edition : byte
{
EDITION_1 = 0,
EDITION_2 = 1,
EDITION_2_1 = 2
}
public class LibIEC61850
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
@ -79,9 +86,9 @@ namespace IEC61850
public UInt16 vlanId;
public UInt16 appId;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=6)]
public byte[] dstAddress = new byte[6];
}
[MarshalAs(UnmanagedType.ByValArray, SizeConst=6)]
public byte[] dstAddress = new byte[6];
}
/// <summary>
/// MMS data access error for MmsValue type MMS_DATA_ACCESS_ERROR
@ -116,7 +123,9 @@ namespace IEC61850
/** periodic transmission of all data set values */
INTEGRITY = 8,
/** general interrogation (on client request) */
GI = 16
GI = 16,
/** Report will be triggered only on rising edge (transient variable) */
TRG_OPT_TRANSIENT = 128
}
/// <summary>
@ -171,7 +180,7 @@ namespace IEC61850
/// </summary>
public class Quality
{
private UInt16 value;
private UInt16 value;
private const UInt16 QUALITY_DETAIL_OVERFLOW = 4;
private const UInt16 QUALITY_DETAIL_OUT_OF_RANGE = 8;
@ -184,6 +193,9 @@ namespace IEC61850
private const UInt16 QUALITY_SOURCE_SUBSTITUTED = 1024;
private const UInt16 QUALITY_TEST = 2048;
private const UInt16 QUALITY_OPERATOR_BLOCKED = 4096;
private const UInt16 QUALITY_DERIVED = 8192;
public ushort Value => value;
public override string ToString ()
{
@ -341,6 +353,17 @@ namespace IEC61850
this.value = (ushort) ((int) this.value & (~QUALITY_OPERATOR_BLOCKED));
}
}
public bool Derived
{
get { return ((this.value & QUALITY_DERIVED) != 0); }
set {
if (value)
this.value |= QUALITY_DERIVED;
else
this.value = (ushort) ((int) this.value & (~QUALITY_DERIVED));
}
}
}
/// <summary>
@ -365,21 +388,21 @@ namespace IEC61850
static extern bool Timestamp_isLeapSecondKnown (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void Timestamp_setLeapSecondKnown (IntPtr self, bool value);
static extern void Timestamp_setLeapSecondKnown (IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool Timestamp_hasClockFailure (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void Timestamp_setClockFailure (IntPtr self, bool value);
static extern void Timestamp_setClockFailure (IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool Timestamp_isClockNotSynchronized (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void Timestamp_setClockNotSynchronized (IntPtr self, bool value);
static extern void Timestamp_setClockNotSynchronized (IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int Timestamp_getSubsecondPrecision (IntPtr self);
@ -628,6 +651,21 @@ namespace IEC61850
NONE = -1
}
/// <summary>
/// Definition for LastAppError error type for control models
/// Used in LastApplError and CommandTermination messages.
/// </summary>
public enum ControlLastApplError {
NO_ERROR = 0,
UNKNOWN = 1,
TIMEOUT_TEST = 2,
OPERATOR_TEST = 3
}
/// <summary>
/// AddCause - additional cause information for control model errors
/// Used in LastApplError and CommandTermination messages.
/// </summary>
public enum ControlAddCause {
ADD_CAUSE_UNKNOWN = 0,
ADD_CAUSE_NOT_SUPPORTED = 1,

File diff suppressed because it is too large Load Diff

@ -0,0 +1,408 @@
/*
* IedServerConfig.cs
*
* Copyright 2018 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 IEC61850.Common;
namespace IEC61850.Server
{
/// <summary>
/// IedServer configuration object
/// </summary>
public class IedServerConfig : IDisposable
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr IedServerConfig_create();
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr IedServerConfig_destroy(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServerConfig_setReportBufferSize(IntPtr self, int reportBufferSize);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int IedServerConfig_getReportBufferSize(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServerConfig_setReportBufferSizeForURCBs(IntPtr self, int reportBufferSize);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int IedServerConfig_getReportBufferSizeForURCBs(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServerConfig_setFileServiceBasePath(IntPtr self, string basepath);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr IedServerConfig_getFileServiceBasePath(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServerConfig_enableFileService(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool enable);
[return: MarshalAs(UnmanagedType.I1)]
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern bool IedServerConfig_isFileServiceEnabled(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServerConfig_setEdition(IntPtr self, byte edition);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern byte IedServerConfig_getEdition(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServerConfig_setMaxMmsConnections(IntPtr self, int maxConnections);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int IedServerConfig_getMaxMmsConnections(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool IedServerConfig_isDynamicDataSetServiceEnabled(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServerConfig_enableDynamicDataSetService(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool enable);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServerConfig_setMaxAssociationSpecificDataSets(IntPtr self, int maxDataSets);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int IedServerConfig_getMaxAssociationSpecificDataSets(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServerConfig_setMaxDomainSpecificDataSets(IntPtr self, int maxDataSets);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int IedServerConfig_getMaxDomainSpecificDataSets(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServerConfig_setMaxDataSetEntries(IntPtr self, int maxDataSetEntries);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int IedServerConfig_getMaxDatasSetEntries(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServerConfig_enableLogService(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool enable);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool IedServerConfig_isLogServiceEnabled(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServerConfig_enableResvTmsForBRCB(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool enable);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool IedServerConfig_isResvTmsForBRCBEnabled(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServerConfig_enableOwnerForRCB(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool enable);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool IedServerConfig_isOwnerForRCBEnabled(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServerConfig_useIntegratedGoosePublisher(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool enable);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool IedServerConfig_getSyncIntegrityReportTimes(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServerConfig_setSyncIntegrityReportTimes(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool enable);
internal IntPtr self;
public IedServerConfig()
{
self = IedServerConfig_create();
}
/// <summary>
/// Gets or sets the size of the report buffer for buffered report control blocks
/// </summary>
/// <value>The size of the report buffer.</value>
public int ReportBufferSize
{
get
{
return IedServerConfig_getReportBufferSize(self);
}
set
{
IedServerConfig_setReportBufferSize(self, value);
}
}
/// <summary>
/// Gets or sets the size of the report buffer for unbuffered report control blocks
/// </summary>
/// <value>The size of the report buffer.</value>
public int ReportBufferSizeForURCBs
{
get
{
return IedServerConfig_getReportBufferSizeForURCBs(self);
}
set
{
IedServerConfig_setReportBufferSizeForURCBs(self, value);
}
}
/// <summary>
/// Gets or sets the file service base path.
/// </summary>
/// <value>The file service base path.</value>
public string FileServiceBasePath
{
get
{
return Marshal.PtrToStringAnsi(IedServerConfig_getFileServiceBasePath(self));
}
set
{
IedServerConfig_setFileServiceBasePath(self, value);
}
}
/// <summary>
/// Enable/Disable file service for MMS
/// </summary>
/// <value><c>true</c> if file service is enabled; otherwise, <c>false</c>.</value>
public bool FileServiceEnabled
{
get
{
return IedServerConfig_isFileServiceEnabled(self);
}
set
{
IedServerConfig_enableFileService(self, value);
}
}
/// <summary>
/// Gets or sets the edition of the IEC 61850 standard to use
/// </summary>
/// <value>The IEC 61850 edition to use.</value>
public Iec61850Edition Edition
{
get
{
return (Iec61850Edition)IedServerConfig_getEdition(self);
}
set
{
IedServerConfig_setEdition(self, (byte)value);
}
}
/// <summary>
/// Gets or sets maximum number of MMS clients
/// </summary>
/// <value>The max number of MMS client connections.</value>
public int MaxMmsConnections
{
get
{
return IedServerConfig_getMaxMmsConnections(self);
}
set
{
IedServerConfig_setMaxMmsConnections(self, value);
}
}
/// <summary>
/// Enable/Disable dynamic data set service for MMS
/// </summary>
/// <value><c>true</c> if dynamic data set service enabled; otherwise, <c>false</c>.</value>
public bool DynamicDataSetServiceEnabled
{
get
{
return IedServerConfig_isDynamicDataSetServiceEnabled(self);
}
set
{
IedServerConfig_enableDynamicDataSetService(self, value);
}
}
/// <summary>
/// Gets or sets the maximum number of data set entries for dynamic data sets
/// </summary>
/// <value>The max. number data set entries.</value>
public int MaxDataSetEntries
{
get
{
return IedServerConfig_getMaxDatasSetEntries(self);
}
set
{
IedServerConfig_setMaxDataSetEntries(self, value);
}
}
/// <summary>
/// Gets or sets the maximum number of association specific (non-permanent) data sets.
/// </summary>
/// <value>The max. number of association specific data sets.</value>
public int MaxAssociationSpecificDataSets
{
get
{
return IedServerConfig_getMaxAssociationSpecificDataSets(self);
}
set
{
IedServerConfig_setMaxAssociationSpecificDataSets(self, value);
}
}
/// <summary>
/// Gets or sets the maximum number of domain specific (permanent) data sets.
/// </summary>
/// <value>The max. numebr of domain specific data sets.</value>
public int MaxDomainSpecificDataSets
{
get
{
return IedServerConfig_getMaxDomainSpecificDataSets(self);
}
set
{
IedServerConfig_setMaxDomainSpecificDataSets(self, value);
}
}
/// <summary>
/// Enable/Disable log service for MMS
/// </summary>
/// <value><c>true</c> if log service is enabled; otherwise, <c>false</c>.</value>
public bool LogServiceEnabled
{
get
{
return IedServerConfig_isLogServiceEnabled(self);
}
set
{
IedServerConfig_enableLogService(self, value);
}
}
/// <summary>
/// Enable/Disable the presence of ResvTms attribute in BRCBs (buffered report control blocks)
/// </summary>
/// <value><c>true</c> if BRCB has ResvTms; otherwise, <c>false</c>. Defaults to true</value>
public bool BRCBHasResvTms
{
get
{
return IedServerConfig_isResvTmsForBRCBEnabled(self);
}
set
{
IedServerConfig_enableResvTmsForBRCB(self, value);
}
}
/// <summary>
/// Enable/Disable the presence of Owner attribute in RCBs (report control blocks)
/// </summary>
/// <value><c>true</c> if RCB has Owner; otherwise, <c>false</c>. Defaults to false</value>
public bool RCBHasOwner
{
get
{
return IedServerConfig_isOwnerForRCBEnabled(self);
}
set
{
IedServerConfig_enableOwnerForRCB(self, value);
}
}
/// <summary>
/// Enable/disable using the integrated GOOSE publisher for configured GoCBs
/// </summary>
/// <value><c>true</c> when integrated GOOSE publisher is used; otherwise, <c>false</c>. Defaults to true</value>
public bool UseIntegratedGoosePublisher
{
set
{
IedServerConfig_useIntegratedGoosePublisher(self, value);
}
}
/// <summary>
/// Enable/Disable synchoronized integrity report times (disabled by default)
/// </summary>
/// <remarks>
/// When this flag is enabled the integrity report generation times are
/// aligned with the UTC epoch. Then the unix time stamps are straight multiples of the
/// integrity interval.
/// </remarks>
/// <value><c>true</c> if sync integrity report times; otherwise, <c>false</c>.</value>
public bool SyncIntegrityReportTimes
{
get
{
return IedServerConfig_getSyncIntegrityReportTimes(self);
}
set
{
IedServerConfig_setSyncIntegrityReportTimes(self, value);
}
}
/// <summary>
/// Releases all resource used by the <see cref="IEC61850.Server.IedServerConfig"/> object.
/// </summary>
/// <remarks>Call <see cref="Dispose"/> when you are finished using the <see cref="IEC61850.Server.IedServerConfig"/>. The
/// <see cref="Dispose"/> method leaves the <see cref="IEC61850.Server.IedServerConfig"/> in an unusable state. After
/// calling <see cref="Dispose"/>, you must release all references to the
/// <see cref="IEC61850.Server.IedServerConfig"/> so the garbage collector can reclaim the memory that the
/// <see cref="IEC61850.Server.IedServerConfig"/> was occupying.</remarks>
public void Dispose()
{
lock (this)
{
if (self != IntPtr.Zero)
{
IedServerConfig_destroy(self);
self = IntPtr.Zero;
}
}
}
~IedServerConfig()
{
Dispose();
}
}
}

@ -59,20 +59,28 @@ namespace IEC61850
[MarshalAs(UnmanagedType.ByValArray, SizeConst=16)] public byte[] value;
}
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[StructLayout(LayoutKind.Sequential)]
private struct NativePSelector
{
public byte size;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] value;
}
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
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_setRemoteAddresses(IntPtr self, UInt32 pSelector, NativeSSelector sSelector, NativeTSelector tSelector);
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_setLocalAddresses(IntPtr self, UInt32 pSelector, NativeSSelector sSelector, NativeTSelector tSelector);
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);
@ -130,7 +138,7 @@ namespace IEC61850
/// <param name='tSelector'>
/// ISO COTP transport layer address
/// </param>
public void SetRemoteAddresses (UInt32 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");
@ -142,6 +150,9 @@ namespace IEC61850
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");
NativeSSelector nativeSSelector;
nativeSSelector.size = (byte) sSelector.Length;
nativeSSelector.value = new byte[16];
@ -149,7 +160,17 @@ namespace IEC61850
for (int i = 0; i < sSelector.Length; i++)
nativeSSelector.value [i] = sSelector [i];
IsoConnectionParameters_setRemoteAddresses(self, pSelector, nativeSSelector, nativeTSelector);
if (pSelector.Length > 16)
throw new ArgumentOutOfRangeException("pSelector", "maximum size (16) exceeded");
NativePSelector nativePSelector;
nativePSelector.size = (byte)pSelector.Length;
nativePSelector.value = new byte[16];
for (int i = 0; i < pSelector.Length; i++)
nativePSelector.value[i] = pSelector[i];
IsoConnectionParameters_setRemoteAddresses(self, nativePSelector, nativeSSelector, nativeTSelector);
}
/// <summary>
@ -178,7 +199,7 @@ namespace IEC61850
/// <param name='tSelector'>
/// ISO COTP transport layer address
/// </param>
public void SetLocalAddresses (UInt32 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");
@ -190,6 +211,9 @@ namespace IEC61850
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");
NativeSSelector nativeSSelector;
nativeSSelector.size = (byte) sSelector.Length;
nativeSSelector.value = new byte[16];
@ -197,7 +221,17 @@ namespace IEC61850
for (int i = 0; i < sSelector.Length; i++)
nativeSSelector.value [i] = sSelector [i];
IsoConnectionParameters_setLocalAddresses(self, pSelector, nativeSSelector, nativeTSelector);
if (pSelector.Length > 16)
throw new ArgumentOutOfRangeException("pSelector", "maximum size (16) exceeded");
NativePSelector nativePSelector;
nativePSelector.size = (byte)pSelector.Length;
nativePSelector.value = new byte[16];
for (int i = 0; i < pSelector.Length; i++)
nativePSelector.value[i] = pSelector[i];
IsoConnectionParameters_setLocalAddresses(self, nativePSelector, nativeSSelector, nativeTSelector);
}
/// <summary>

@ -32,11 +32,10 @@ namespace IEC61850
{
namespace Common
{
/// <summary>
/// This class is used to hold MMS data values of different types.
/// </summary>
public class MmsValue : IEnumerable
public class MmsValue : IEnumerable, IDisposable
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsValue_toString (IntPtr self);
@ -55,7 +54,10 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool MmsValue_getBoolean (IntPtr self);
static extern bool MmsValue_getBoolean (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void MmsValue_setBoolean(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 MmsValue_getBitStringAsInteger (IntPtr self);
@ -63,11 +65,17 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void MmsValue_setBitStringFromInteger(IntPtr self, UInt32 intValue);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 MmsValue_getBitStringAsIntegerBigEndian(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void MmsValue_setBitStringFromIntegerBigEndian(IntPtr self, UInt32 intValue);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int MmsValue_getBitStringSize(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void MmsValue_setBitStringBit(IntPtr self, int bitPos, bool value);
static extern void MmsValue_setBitStringBit(IntPtr self, int bitPos, [MarshalAs(UnmanagedType.I1)] bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
@ -76,6 +84,9 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern Int32 MmsValue_toInt32 (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void MmsValue_setInt32(IntPtr self, int value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern Int64 MmsValue_toInt64 (IntPtr self);
@ -113,7 +124,7 @@ namespace IEC61850
static extern UInt32 MmsValue_toUnixTimestamp (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsValue_newBoolean (bool value);
static extern IntPtr MmsValue_newBoolean ([MarshalAs(UnmanagedType.I1)] bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsValue_newFloat (float value);
@ -136,6 +147,21 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsValue_newVisibleString(string value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsValue_newVisibleStringWithSize(int size);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void MmsValue_setVisibleString(IntPtr self, string value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsValue_createArray(IntPtr elementType, int size);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsValue_createEmptyArray(int size);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsValue_createEmptyStructure(int size);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsValue_newOctetString(int size, int maxSize);
@ -148,7 +174,13 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt16 MmsValue_getOctetStringMaxSize(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern byte MmsValue_getOctetStringOctet(IntPtr self, int pos);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void MmsValue_setOctetStringOctet(IntPtr self, int pos, byte value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsValue_getOctetStringBuffer(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
@ -156,7 +188,7 @@ namespace IEC61850
static extern bool MmsValue_equals(IntPtr self, IntPtr otherValue);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsValue_newBinaryTime (bool timeOfDay);
static extern IntPtr MmsValue_newBinaryTime ([MarshalAs(UnmanagedType.I1)] bool timeOfDay);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void MmsValue_setBinaryTime (IntPtr self, UInt64 timestamp);
@ -164,15 +196,26 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern ulong MmsValue_getBinaryTimeAsUtcMs (IntPtr self);
[DllImport ("iec61850", CallingConvention=CallingConvention.Cdecl)]
[DllImport ("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsValue_newUtcTimeByMsTime (UInt64 timestamp);
[DllImport("iec61850", CallingConvention=CallingConvention.Cdecl)]
static extern int MmsValue_getDataAccessError(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void MmsValue_setElement(IntPtr complexValue, int index, IntPtr elementValue);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsVariableSpecification_getChildValue(IntPtr self, IntPtr value, string childId);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsValue_clone(IntPtr self);
internal IntPtr valueReference; /* reference to native MmsValue instance */
private bool responsableForDeletion; /* if .NET wrapper is responsable for the deletion of the native MmsValue instance */
private bool responsableForDeletion = false; /* if .NET wrapper is responsable for the deletion of the native MmsValue instance */
// TODO make internal
public MmsValue (IntPtr value)
internal MmsValue (IntPtr value)
{
valueReference = value;
this.responsableForDeletion = false;
@ -214,16 +257,32 @@ namespace IEC61850
valueReference = MmsValue_newIntegerFromInt64 (value);
}
/// <summary>
/// Create a new <see cref="IEC61850.Common.MmsValue"/> instance of type MMS_VISIBLE_STRING.
/// </summary>
/// <param name="value">Value.</param>
public MmsValue (string value)
{
valueReference = MmsValue_newVisibleString(value);
}
~MmsValue ()
{
if (responsableForDeletion)
MmsValue_delete (valueReference);
}
public void Dispose()
{
lock (this) {
if (valueReference != IntPtr.Zero) {
if (responsableForDeletion)
MmsValue_delete (valueReference);
valueReference = IntPtr.Zero;
}
}
}
~MmsValue ()
{
Dispose();
}
/// <summary>
/// Create a new MmsValue instance of type MMS_BIT_STRING.
@ -270,6 +329,53 @@ namespace IEC61850
this.setOctetString (octetString);
}
/// <summary>
/// Create a new MmsValue instance of type MMS_ARRAY. Array elements have the fiven type
/// </summary>
/// <returns>the newly created array</returns>
/// <param name="elementType">array element type</param>
/// <param name="size">number of array elements</param>
public static MmsValue NewArray(MmsVariableSpecification elementType, int size)
{
if (size < 1)
throw new MmsValueException ("array requires at least one element");
IntPtr newValue = MmsValue_createArray (elementType.self, size);
return new MmsValue (newValue, true);
}
/// <summary>
/// Create a new MmsValue instance of type MMS_ARRAY. Array elements are not initialized!
/// </summary>
/// <returns>the newly created array</returns>
/// <param name="size">number of array elements</param>
public static MmsValue NewEmptyArray(int size)
{
if (size < 1)
throw new MmsValueException ("array requires at least one element");
IntPtr newValue = MmsValue_createEmptyArray (size);
return new MmsValue (newValue, true);
}
/// <summary>
/// Create a new MmsValue instance of type MMS_STRUCTURE. Structure elements are not initialized!
/// </summary>
/// <returns>the newly created array</returns>
/// <param name="size">number of structure elements</param>
public static MmsValue NewEmptyStructure(int size)
{
if (size < 1)
throw new MmsValueException ("structure requires at least one element");
IntPtr newValue = MmsValue_createEmptyStructure (size);
return new MmsValue (newValue, true);
}
/// <summary>
/// Create a new MmsValue instance of type MMS_BINARY_TIME
/// </summary>
@ -310,12 +416,45 @@ namespace IEC61850
}
/// <summary>
/// Gets the type of the value
/// Create a new MmsValue instance of type MMS_UTC_TIME
/// </summary>
/// <returns>
/// The type.
/// </returns>
public new MmsType GetType ()
/// <returns>the new MmsValue instance.</returns>
/// <param name="timestamp">the time value as milliseconds since epoch (1.1.1970 UTC).</param>
public static MmsValue NewUtcTime (UInt64 timestamp)
{
IntPtr newValue = MmsValue_newUtcTimeByMsTime (timestamp);
return new MmsValue (newValue, true);
}
/// <summary>
/// Create a new MmsValue instance of type MMS_VISIBLE_STRING - empty string with given maximum size
/// </summary>
/// <param name="size">The maximum size </param>
/// <returns></returns>
public static MmsValue NewVisibleString(int size, bool responsibleForDeletion = false)
{
IntPtr newValue = MmsValue_newVisibleStringWithSize(size);
return new MmsValue(newValue, responsibleForDeletion);
}
/// <summary>
/// Set the value of an MmsValue instance of type MMS_VISIBLE_STRING
/// </summary>
/// <param name="value">the new string value</param>
public void SetVisibleString(string value)
{
MmsValue_setVisibleString(valueReference, value);
}
/// <summary>
/// Gets the type of the value
/// </summary>
/// <returns>
/// The type.
/// </returns>
public new MmsType GetType ()
{
return (MmsType)MmsValue_getType (valueReference);
}
@ -385,6 +524,11 @@ namespace IEC61850
throw new MmsValueException ("Operation not supported for this type");
}
/// <summary>
/// Sets the value of an octet string by a byte array
/// </summary>
/// <param name="octetString">Byte array containing the bytes of the octet string.</param>
/// <exception cref="MmsValueException">This exception is thrown if the value has the wrong type or the byte array is too large.</exception>
public void setOctetString (byte[] octetString)
{
if (GetType () == MmsType.MMS_OCTET_STRING) {
@ -398,6 +542,26 @@ namespace IEC61850
throw new MmsValueException ("Operation not supported for this type");
}
/// <summary>
/// Gets the octet string octet.
/// </summary>
/// <returns>The octet string octet.</returns>
/// <param name="pos">Position of the octet in the octet string.</param>
public byte GetOctetStringOctet(int pos)
{
return MmsValue_getOctetStringOctet(valueReference, pos);
}
/// <summary>
/// Sets the octet string octet.
/// </summary>
/// <param name="pos">Position of the octet in the octet string.</param>
/// <param name="value">The octet string octet.</param>
public void SetOctetStringOctet(int pos, byte value)
{
MmsValue_setOctetStringOctet(valueReference, pos, value);
}
/// <summary>
/// Get an element of an array or structure
/// </summary>
@ -427,17 +591,60 @@ namespace IEC61850
throw new MmsValueException ("Value is of wrong type");
}
/// <summary>
/// Sets the element of an array or structure
/// </summary>
/// <remarks>
/// After calling this function the native memory of the element will be managed by the array or structure.
/// Therefore an element can only be used in a single array or structure.
/// When the value is required in multiple arrays or structures
/// a clone has to be created before using this function!
/// To be save, always use a clone for setting the element.
/// </remarks>
/// <param name="index">index of the element starting with 0</param>
/// <param name="elementValue">MmsValue instance that will be used as element value</param>
/// <exception cref="MmsValueException">This exception is thrown if the value has the wrong type.</exception>
/// <exception cref="MmsValueException">This exception is thrown if the index is out of range.</exception>
public void SetElement(int index, MmsValue elementValue)
{
MmsType elementType = GetType();
public MmsDataAccessError GetDataAccessError ()
{
if (GetType () == MmsType.MMS_DATA_ACCESS_ERROR) {
int errorCode = MmsValue_getDataAccessError (valueReference);
if ((elementType == MmsType.MMS_ARRAY) || (elementType == MmsType.MMS_STRUCTURE))
{
return (MmsDataAccessError)errorCode;
}
else
throw new MmsValueException ("Value is of wrong type");
}
if ((index >= 0) && (index < Size()))
{
if (elementValue != null)
{
MmsValue_setElement(valueReference, index, elementValue.valueReference);
/* will be deleted by structure */
elementValue.responsableForDeletion = false;
}
else
MmsValue_setElement(valueReference, index, IntPtr.Zero);
}
else
throw new MmsValueException("Index out of bounds");
}
else
throw new MmsValueException("Value is of wrong type");
}
public MmsDataAccessError GetDataAccessError()
{
if (GetType() == MmsType.MMS_DATA_ACCESS_ERROR)
{
int errorCode = MmsValue_getDataAccessError(valueReference);
return (MmsDataAccessError)errorCode;
}
else
throw new MmsValueException("Value is of wrong type");
}
/// <summary>
/// Gets the timestamp value as UTC time in s (UNIX time stamp).
@ -611,19 +818,34 @@ namespace IEC61850
throw new MmsValueException ("Value type is not integer");
return MmsValue_toInt32 (valueReference);
}
}
/// <summary>
/// Sets the 32 bit signed integer.
/// </summary>
/// <param name='value'>
/// the new value to set
/// </param>
/// <exception cref="MmsValueException">This exception is thrown if the value has the wrong type.</exception>
public void SetInt32(int value)
{
if (GetType() != MmsType.MMS_INTEGER)
throw new MmsValueException("Value type is not integer");
/// <summary>
/// Return the value as 64 bit signed integer.
/// </summary>
/// <description>
/// Return the value as 64 bit signed integer (Int64).
/// The value has to be of type MMS_INTEGER.
/// </description>
/// <returns>
/// the value if the object as 64 bit signed integer
/// </returns>
/// <exception cref="MmsValueException">This exception is thrown if the value has the wrong type.</exception>
MmsValue_setInt32(valueReference, value);
}
/// <summary>
/// Return the value as 64 bit signed integer.
/// </summary>
/// <description>
/// Return the value as 64 bit signed integer (Int64).
/// The value has to be of type MMS_INTEGER.
/// </description>
/// <returns>
/// the value if the object as 64 bit signed integer
/// </returns>
/// <exception cref="MmsValueException">This exception is thrown if the value has the wrong type.</exception>
public Int64 ToInt64 ()
{
if (GetType () != MmsType.MMS_INTEGER)
@ -667,7 +889,23 @@ namespace IEC61850
MmsValue_setBitStringFromInteger(valueReference, intValue);
}
public void SetBit (int bitPos, bool bitValue)
public UInt32 BitStringToUInt32BigEndian()
{
if (GetType() != MmsType.MMS_BIT_STRING)
throw new MmsValueException("Value type is not bit string");
return MmsValue_getBitStringAsIntegerBigEndian(valueReference);
}
public void BitStringFromUInt32BigEndian(UInt32 intValue)
{
if (GetType() != MmsType.MMS_BIT_STRING)
throw new MmsValueException("Value type is not bit string");
MmsValue_setBitStringFromIntegerBigEndian(valueReference, intValue);
}
public void SetBit (int bitPos, bool bitValue)
{
if (GetType () != MmsType.MMS_BIT_STRING)
throw new MmsValueException("Value type is not bit string");
@ -716,15 +954,30 @@ namespace IEC61850
return MmsValue_getBoolean (valueReference);
else
throw new MmsValueException ("Value type is not boolean");
}
}
/// <summary>
/// Sets the boolean value of an MMS_BOOLEAN instance
/// </summary>
/// <param name='value'>
/// the new value to set
/// </param>
/// <exception cref="MmsValueException">This exception is thrown if the value has the wrong type.</exception>
public void SetBoolean(bool value)
{
if (GetType() != MmsType.MMS_BOOLEAN)
throw new MmsValueException("Value type is not boolean");
/// <summary>
/// Gets the float value of an MMS_FLOAT instance
/// </summary>
/// <returns>
/// The float value
/// </returns>
/// <exception cref="MmsValueException">This exception is thrown if the value has the wrong type.</exception>
MmsValue_setBoolean(valueReference, value);
}
/// <summary>
/// Gets the float value of an MMS_FLOAT instance
/// </summary>
/// <returns>
/// The float value
/// </returns>
/// <exception cref="MmsValueException">This exception is thrown if the value has the wrong type.</exception>
public float ToFloat ()
{
if (GetType () == MmsType.MMS_FLOAT)
@ -778,6 +1031,41 @@ namespace IEC61850
throw new MmsValueException ("Value type is not float");
}
/// <summary>
/// Gets the child value with the given name
/// </summary>
/// <returns>the child value or null if no matching child has been found.</returns>
/// <param name="childPath">path specifying the child using '.' or '$' as path element separator.</param>
/// <param name="specification">the variable specification to use.</param>
public MmsValue GetChildValue(string childPath, MmsVariableSpecification specification)
{
StringBuilder childPathStr = new StringBuilder(childPath);
childPathStr.Replace('.', '$');
IntPtr childPtr = MmsVariableSpecification_getChildValue(specification.self, valueReference, childPathStr.ToString());
if (childPtr == IntPtr.Zero)
return null;
else
{
return new MmsValue(childPtr);
}
}
/// <summary>
/// Get an identical copy of this instance
/// </summary>
public MmsValue Clone()
{
IntPtr clonePtr = MmsValue_clone(valueReference);
if (clonePtr == IntPtr.Zero)
return null;
return new MmsValue(clonePtr, true);
}
public override bool Equals (object obj)
{
MmsValue otherValue = (MmsValue) obj;
@ -828,9 +1116,31 @@ namespace IEC61850
return retString;
}
case MmsType.MMS_ARRAY:
{
string retString = "[";
bool first = true;
foreach (MmsValue element in this) {
if (first) {
retString += element.ToString ();
first = false;
} else {
retString += ", " + element.ToString ();
}
}
retString += "]";
return retString;
}
case MmsType.MMS_DATA_ACCESS_ERROR:
return "error: " + GetDataAccessError().ToString();
default:
return "unknown";
return "unknown (type:" + GetType().ToString() + ")";
}
}

@ -26,6 +26,7 @@ using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Collections;
using System.Text;
namespace IEC61850
{
@ -39,9 +40,6 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void MmsVariableSpecification_destroy(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsVariableSpecification_getChildValue(IntPtr self, IntPtr value, string childId);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsVariableSpecification_getNamedVariableRecursive(IntPtr variable, string nameId);
@ -63,13 +61,20 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int MmsVariableSpecification_getExponentWidth(IntPtr self);
private IntPtr self;
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern bool MmsVariableSpecification_isValueOfType(IntPtr self, IntPtr value);
internal IntPtr self;
private bool responsableForDeletion;
internal MmsVariableSpecification (IntPtr self)
/* 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;
this.parent = parent;
}
internal MmsVariableSpecification (IntPtr self, bool responsableForDeletion)
@ -78,6 +83,27 @@ namespace IEC61850
this.responsableForDeletion = responsableForDeletion;
}
/// <summary>
/// Get a child variable specification by its name
/// </summary>
/// <returns>the varibable specification of the child, or null if no such child is existing.</returns>
/// <param name="name">The child name (can also be a path separating the elements with '.' or '$')</param>
public MmsVariableSpecification GetChildByName(string name)
{
StringBuilder nameId = new StringBuilder(name);
nameId.Replace('.', '$');
IntPtr varSpecPtr = MmsVariableSpecification_getNamedVariableRecursive(self, nameId.ToString());
if (varSpecPtr != IntPtr.Zero)
{
return new MmsVariableSpecification(varSpecPtr, this);
}
else
return null;
}
~MmsVariableSpecification ()
{
if (responsableForDeletion)
@ -106,7 +132,7 @@ namespace IEC61850
{
if (GetType() == MmsType.MMS_ARRAY) {
IntPtr varSpecPtr = MmsVariableSpecification.MmsVariableSpecification_getArrayElementSpecification(self);
return new MmsVariableSpecification(varSpecPtr);
return new MmsVariableSpecification(varSpecPtr, this);
}
else
throw new MmsValueException ("specification is of wrong type");
@ -127,7 +153,7 @@ namespace IEC61850
if ((index >= 0) && (index < Size ())) {
IntPtr varSpecPtr = MmsVariableSpecification_getChildSpecificationByIndex(self, index);
return new MmsVariableSpecification(varSpecPtr);
return new MmsVariableSpecification(varSpecPtr, this);
}
else
throw new MmsValueException ("Index out of bounds");
@ -157,6 +183,16 @@ namespace IEC61850
return MmsVariableSpecification_getSize(self);
}
/// <summary>
/// Determines whether the given value object matches this type
/// </summary>
/// <returns><c>true</c> if the value matches this type; otherwise, <c>false</c>.</returns>
/// <param name="value">the value to test.</param>
public bool IsValueOfType(MmsValue value)
{
return MmsVariableSpecification_isValueOfType(self, value.valueReference);
}
IEnumerator IEnumerable.GetEnumerator ()
{
return new MmsVariableSpecificationEnumerator (this);

@ -1,7 +1,7 @@
/*
* ReportControlBlock.cs
*
* Copyright 2014 Michael Zillgith
* Copyright 2014-2018 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -34,8 +34,13 @@ namespace IEC61850
/// <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);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void InternalReportHandler (IntPtr parameter, IntPtr report);
/// <summary>
/// Report control block (RCB) representation.
/// </summary>
@ -44,16 +49,13 @@ namespace IEC61850
/// Values from the server will only be read when the GetRCBValues method is called.
/// Values at the server are only affected when the SetRCBValues method is called.
/// </description>
public class ReportControlBlock
public class ReportControlBlock : IDisposable
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientReportControlBlock_create (string dataAttributeReference);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr IedConnection_getRCBValues (IntPtr connection, out int error, string rcbReference, IntPtr updateRcb);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedConnection_setRCBValues (IntPtr connection, out int error, IntPtr rcb, UInt32 parametersMask, bool singleRequest);
static extern void ClientReportControlBlock_destroy (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
@ -70,14 +72,14 @@ namespace IEC61850
static extern bool ClientReportControlBlock_getRptEna (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_setRptEna(IntPtr self, bool rptEna);
static extern void ClientReportControlBlock_setRptEna(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool rptEna);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientReportControlBlock_getResv (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_setResv (IntPtr self, bool resv);
static extern void ClientReportControlBlock_setResv (IntPtr self, [MarshalAs(UnmanagedType.I1)] bool resv);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientReportControlBlock_getDataSetReference (IntPtr self);
@ -120,17 +122,21 @@ namespace IEC61850
static extern bool ClientReportControlBlock_getGI (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_setGI (IntPtr self, bool gi);
static extern void ClientReportControlBlock_setGI (IntPtr self, [MarshalAs(UnmanagedType.I1)] bool gi);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientReportControlBlock_getPurgeBuf (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_setPurgeBuf (IntPtr self, bool purgeBuf);
static extern void ClientReportControlBlock_setPurgeBuf (IntPtr self, [MarshalAs(UnmanagedType.I1)] bool purgeBuf);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern Int32 ClientReportControlBlock_getResvTms (IntPtr self);
[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);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_setResvTms (IntPtr self, Int16 resvTms);
@ -147,19 +153,9 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientReportControlBlock_getOwner (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedConnection_installReportHandler (IntPtr connection, string rcbReference, string rptId, InternalReportHandler handler,
IntPtr handlerParameter);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedConnection_uninstallReportHandler(IntPtr connection, string rcbReference);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void InternalReportHandler (IntPtr parameter, IntPtr report);
private IntPtr self;
private IntPtr connection;
private IedConnection iedConnection = null;
internal IntPtr self;
private IedConnection iedConnection = null;
private string objectReference;
private bool flagRptId = false;
private bool flagRptEna = false;
@ -221,14 +217,11 @@ namespace IEC61850
internal ReportControlBlock (string objectReference, IedConnection iedConnection, IntPtr connection)
{
self = ClientReportControlBlock_create (objectReference);
this.iedConnection = iedConnection;
this.connection = connection;
this.objectReference = objectReference;
}
internal void DisposeInternal()
{
IedConnection_uninstallReportHandler(connection, objectReference);
if (self != IntPtr.Zero) {
this.iedConnection = iedConnection;
this.objectReference = objectReference;
}
}
/// <summary>
@ -239,11 +232,25 @@ namespace IEC61850
/// 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()
public void Dispose()
{
DisposeInternal ();
lock (this) {
if (self != IntPtr.Zero) {
iedConnection.UninstallReportHandler (objectReference);
iedConnection.RemoveRCB (this);
iedConnection.RemoveRCB (this);
ClientReportControlBlock_destroy (self);
self = IntPtr.Zero;
}
}
}
~ReportControlBlock()
{
Dispose ();
}
public string GetObjectReference ()
@ -279,9 +286,10 @@ namespace IEC61850
{
internalHandler = new InternalReportHandler(internalReportHandler);
}
iedConnection.InstallReportHandler (objectReference, reportId, internalHandler);
IedConnection_installReportHandler(this.connection, objectReference, reportId, internalHandler, IntPtr.Zero);
reportHandlerInstalled = true;
reportHandlerInstalled = true;
}
}
@ -293,12 +301,24 @@ namespace IEC61850
{
int error;
IedConnection_getRCBValues (connection, out error, objectReference, self);
iedConnection.GetRCBValues (out error, objectReference, self);
if (error != 0)
throw new IedConnectionException ("getRCBValues service failed", error);
}
/// <summary>
/// Read all RCB values from the server - asynchronous version
/// </summary>
/// <returns>the invoke ID of the request</returns>
/// <param name="handler">user provided callback function</param>
/// <param name="parameter">user provided callback parameter</param>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public UInt32 GetRCBValuesAsync(GetRCBValuesHandler handler, object parameter)
{
return iedConnection.GetRCBValuesAsync(GetObjectReference(), this, handler, parameter);
}
/// <summary>
/// Write changed RCB values to the server.
/// </summary>
@ -312,17 +332,7 @@ namespace IEC61850
SetRCBValues (true);
}
/// <summary>
/// Write changed RCB values to the server.
/// </summary>
/// <description>
/// This function will only write the RCB values that were set by one of the setter methods.
/// </description>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
/// <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)
private UInt32 CreateParametersMask()
{
UInt32 parametersMask = 0;
@ -368,10 +378,41 @@ namespace IEC61850
if (flagResvTms)
parametersMask += 16384;
int error;
return parametersMask;
}
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);
}
/// <summary>
/// Write changed RCB values to the server.
/// </summary>
/// <description>
/// This function will only write the RCB values that were set by one of the setter methods.
/// </description>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
/// <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)
{
UInt32 parametersMask = CreateParametersMask();
IedConnection_setRCBValues (connection, out error, self, parametersMask, singleRequest);
bool flagRptId = this.flagRptId;
int error;
iedConnection.SetRCBValues (out error, self, parametersMask, singleRequest);
resetSendFlags();
if (error != 0)
@ -710,6 +751,60 @@ namespace IEC61850
flagOptFlds = true;
}
/// <summary>
/// Check if the report control block has the "ResvTms" attribute.
/// </summary>
/// <returns><c>true</c>, if ResvTms is available, <c>false</c> otherwise.</returns>
public bool HasResvTms()
{
return ClientReportControlBlock_hasResvTms(self);
}
/// <summary>
/// Gets the ResvTms (reservation time) value
/// </summary>
/// <remarks>
/// Only for BRCB.
/// Value of -1 indicate the BRCB is exclusively reserved for a set of client based upon configuration.
/// Value of 0 means that the BRCB is not reserved.
/// Positive value indicates that the BRCB is reserved dynamically and the value is the number of
/// seconds for reservation after association loss.
/// </remarks>
/// <returns>The reservation time</returns>
public Int16 GetResvTms()
{
return ClientReportControlBlock_getResvTms(self);
}
/// <summary>
/// Sets the ResvTms (reservation time) value
/// </summary>
/// <param name="resvTms">the reservation time value</param>
public void SetResvTms(Int16 resvTms)
{
ClientReportControlBlock_setResvTms(self, resvTms);
flagResvTms = true;
}
/// <summary>
/// Gets the current owner of the RCB
/// </summary>
/// <returns>The owner information, or null when no owner information is available.</returns>
public byte[] GetOwner()
{
IntPtr mmsValuePtr = ClientReportControlBlock_getOwner(self);
if (mmsValuePtr != IntPtr.Zero)
{
MmsValue octetStringVal = new MmsValue(mmsValuePtr);
return octetStringVal.getOctetString();
}
else
return null;
}
}
}

@ -1,7 +1,7 @@
/*
* Reporting.cs
*
* Copyright 2014 Michael Zillgith
* Copyright 2014-2018 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -28,86 +28,78 @@ using System.Collections.Generic;
namespace IEC61850
{
namespace Client
{
public partial class IedConnection
{
namespace Client
{
public partial class IedConnection
{
private List<ReportControlBlock> activeRCBs = null;
private List<ReportControlBlock> activeRCBs = null;
private void cleanupRCBs()
{
if (activeRCBs != null) {
foreach (ReportControlBlock rcb in activeRCBs) {
rcb.DisposeInternal ();
}
}
}
public ReportControlBlock GetReportControlBlock (string rcbObjectReference)
{
var newRCB = new ReportControlBlock (rcbObjectReference, this, connection);
public ReportControlBlock GetReportControlBlock(string rcbObjectReference)
{
var newRCB = new ReportControlBlock(rcbObjectReference, this, connection);
if (activeRCBs == null)
activeRCBs = new List<ReportControlBlock> ();
if (activeRCBs == null)
activeRCBs = new List<ReportControlBlock>();
activeRCBs.Add (newRCB);
activeRCBs.Add(newRCB);
return newRCB;
}
return newRCB;
}
internal void RemoveRCB(ReportControlBlock rcb) {
if (activeRCBs != null) {
activeRCBs.Remove (rcb);
}
}
internal void RemoveRCB(ReportControlBlock rcb)
{
if (activeRCBs != null)
{
activeRCBs.Remove(rcb);
}
}
}
}
public enum ReasonForInclusion
{
/** the element is not included in the received report */
REASON_NOT_INCLUDED = 0,
[Flags]
public enum ReasonForInclusion
{
/** the element is not included in the received report */
REASON_NOT_INCLUDED = 0,
/** the element is included due to a change of the data value */
REASON_DATA_CHANGE = 1,
/** the element is included due to a change of the data value */
REASON_DATA_CHANGE = 1,
/** the element is included due to a change in the quality of data */
REASON_QUALITY_CHANGE = 2,
/** the element is included due to a change in the quality of data */
REASON_QUALITY_CHANGE = 2,
/** the element is included due to an update of the data value */
REASON_DATA_UPDATE = 3,
/** the element is included due to an update of the data value */
REASON_DATA_UPDATE = 4,
/** the element is included due to a periodic integrity report task */
REASON_INTEGRITY = 4,
/** the element is included due to a periodic integrity report task */
REASON_INTEGRITY = 8,
/** the element is included due to a general interrogation by the client */
REASON_GI = 5,
/** the element is included due to a general interrogation by the client */
REASON_GI = 16,
/** the reason for inclusion is unknown */
REASON_UNKNOWN = 6
}
/** the reason for inclusion is unknown */
REASON_UNKNOWN = 32
}
/// <summary>
/// A class to hold the contents of a received report
/// </summary>
public class Report
{
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientReport_hasTimestamp (IntPtr self);
static extern bool ClientReport_hasTimestamp(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt64 ClientReport_getTimestamp (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt64 ClientReport_getTimestamp(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientReport_getDataSetValues(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientReport_getDataSetValues(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int ClientReport_getReasonForInclusion(IntPtr self, int elementIndex);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int ClientReport_getReasonForInclusion(IntPtr self, int elementIndex);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
@ -135,7 +127,7 @@ namespace IEC61850
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientReport_hasBufOvfl(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientReport_getBufOvfl(IntPtr self);
@ -146,28 +138,37 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientReport_getRcbReference(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientReport_getDataSetName(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientReport_getDataSetName(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientReport_getRptId(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientReport_getEntryId(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientReport_getEntryId(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientReport_getDataReference(IntPtr self, int elementIndex);
private IntPtr self;
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern bool ClientReport_hasSubSeqNum(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt16 ClientReport_getSubSeqNum(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern bool ClientReport_getMoreSeqmentsFollow(IntPtr self);
private IntPtr self;
private IntPtr dataSetValues = IntPtr.Zero;
private IntPtr dataSetValues = IntPtr.Zero;
private MmsValue values = null;
private MmsValue values = null;
internal Report (IntPtr self)
{
this.self = self;
}
internal Report(IntPtr self)
{
this.self = self;
}
/// <summary>
/// Determines whether the report has a timestamp.
@ -175,10 +176,10 @@ namespace IEC61850
/// <returns>
/// <c>true</c> if this report has a timestamp; otherwise, <c>false</c>.
/// </returns>
public bool HasTimestamp ()
{
return ClientReport_hasTimestamp (self);
}
public bool HasTimestamp()
{
return ClientReport_hasTimestamp(self);
}
/// <summary>
/// Gets the timestamp.
@ -186,55 +187,94 @@ namespace IEC61850
/// <returns>
/// The timestamp as milliseconds since 1.1.1970 UTC 00:00 or 0 if no timestamp is present.
/// </returns>
public UInt64 GetTimestamp ()
{
if (HasTimestamp ())
return ClientReport_getTimestamp (self);
else
return 0;
}
public bool HasDataSetName ()
public UInt64 GetTimestamp()
{
if (HasTimestamp())
return ClientReport_getTimestamp(self);
else
return 0;
}
public bool HasDataSetName()
{
return ClientReport_hasDataSetName(self);
}
public bool HasDataReference ()
public bool HasDataReference()
{
return ClientReport_hasDataReference(self);
}
public bool HasConfRev ()
public bool HasConfRev()
{
return ClientReport_hasConfRev(self);
}
public UInt32 GetConfRev ()
public UInt32 GetConfRev()
{
return ClientReport_getConfRev(self);
}
public bool HasBufOvfl ()
public bool HasBufOvfl()
{
return ClientReport_hasBufOvfl(self);
}
public bool GetBufOvfl ()
{
return ClientReport_getBufOvfl(self);
}
public bool GetBufOvfl()
{
return ClientReport_getBufOvfl(self);
}
public bool HasSeqNum ()
/// <summary>
/// Indicates if the report contains a sequence number (SeqNum) field
/// </summary>
/// <returns><c>true</c> if this instance has SeqNum; otherwise, <c>false</c>.</returns>
public bool HasSeqNum()
{
return ClientReport_hasSeqNum(self);
}
public UInt16 GetSeqNum ()
/// <summary>
/// Gets the value of the SeqNum field
/// </summary>
/// <returns>The report sequence number</returns>
public UInt16 GetSeqNum()
{
return ClientReport_getSeqNum(self);
}
public bool HasReasonForInclusion ()
/// <summary>
/// Indicates if the report contains a sub sequence number (SubSeqNum) and more segments follow (MoreSegmentsFollow) field
/// </summary>
/// <returns><c>true</c> if this instance has SubSeqNum and MoreSegmentsFollow; otherwise, <c>false</c>.</returns>
public bool HasSubSeqNum()
{
return ClientReport_hasSubSeqNum(self);
}
/// <summary>
/// Gets the sub sequence number (SubSeqNum) value of a segmented report
/// </summary>
/// <returns>The sub sequence number.</returns>
public UInt16 GetSubSeqNum()
{
return ClientReport_getSubSeqNum(self);
}
/// <summary>
/// Gets the more segments follow (MoreSegmentsFollow) flag
/// </summary>
/// <returns><c>true</c>, if more report segments follow, <c>false</c> otherwise.</returns>
public bool GetMoreSegmentsFollow()
{
return ClientReport_getMoreSeqmentsFollow(self);
}
/// <summary>
/// Determines whether this report contains reason for inclusion information
/// </summary>
/// <returns><c>true</c> if this report contains reason for inclusion information; otherwise, <c>false</c>.</returns>
public bool HasReasonForInclusion()
{
return ClientReport_hasReasonForInclusion(self);
}
@ -245,19 +285,20 @@ namespace IEC61850
/// <returns>
/// The data set values.
/// </returns>
public MmsValue GetDataSetValues ()
{
if (dataSetValues == IntPtr.Zero) {
dataSetValues = ClientReport_getDataSetValues(self);
public MmsValue GetDataSetValues()
{
if (dataSetValues == IntPtr.Zero)
{
dataSetValues = ClientReport_getDataSetValues(self);
if (dataSetValues == IntPtr.Zero)
throw new IedConnectionException("No report values available yet");
if (dataSetValues == IntPtr.Zero)
throw new IedConnectionException("No report values available yet");
values = new MmsValue(dataSetValues);
}
values = new MmsValue(dataSetValues);
}
return values;
}
return values.Clone();
}
/// <summary>
/// Gets the reason for inclusion of data set member with the given index
@ -268,36 +309,37 @@ namespace IEC61850
/// <param name='index'>
/// index of the data set member in the data set
/// </param>
public ReasonForInclusion GetReasonForInclusion (int index)
{
if (values == null) {
GetDataSetValues ();
public ReasonForInclusion GetReasonForInclusion(int index)
{
if (values == null)
{
GetDataSetValues();
if (values == null)
throw new IedConnectionException("No ReasonForInclusion available yet");
}
if (values == null)
throw new IedConnectionException("No ReasonForInclusion available yet");
}
int dataSetSize = values.Size();
int dataSetSize = values.Size();
if (index >= dataSetSize)
throw new IedConnectionException("data set index out of range (count = " + dataSetSize + ")");
if (index >= dataSetSize)
throw new IedConnectionException("data set index out of range (count = " + dataSetSize + ")");
return (ReasonForInclusion) ClientReport_getReasonForInclusion(self, index);
}
return (ReasonForInclusion)ClientReport_getReasonForInclusion(self, index);
}
public string GetRcbReference ()
public string GetRcbReference()
{
IntPtr rcbRef = ClientReport_getRcbReference(self);
return Marshal.PtrToStringAnsi (rcbRef);
return Marshal.PtrToStringAnsi(rcbRef);
}
public string GetDataSetName ()
{
IntPtr dataSetName = ClientReport_getDataSetName (self);
public string GetDataSetName()
{
IntPtr dataSetName = ClientReport_getDataSetName(self);
return Marshal.PtrToStringAnsi (dataSetName);
}
return Marshal.PtrToStringAnsi(dataSetName);
}
/// <summary>
/// Gets the data reference for the specified data set element
@ -308,7 +350,7 @@ namespace IEC61850
/// <param name='index'>
/// index of the data set element starting with 0
/// </param>
public string GetDataReference (int index)
public string GetDataReference(int index)
{
IntPtr dataRef = ClientReport_getDataReference(self, index);
@ -318,35 +360,36 @@ namespace IEC61850
return null;
}
public string GetRptId ()
public string GetRptId()
{
IntPtr rptId = ClientReport_getRptId(self);
if (rptId == IntPtr.Zero)
return GetRcbReference();
else
return Marshal.PtrToStringAnsi (rptId);
return Marshal.PtrToStringAnsi(rptId);
}
/// <summary>
/// Gets the EntryID of this report.
/// </summary>
/// <returns>The entryID as a byte array representing an MMS octet string.</returns>
public byte[] GetEntryId ()
{
IntPtr entryIdRef = ClientReport_getEntryId (self);
/// <summary>
/// Gets the EntryID of this report.
/// </summary>
/// <returns>The entryID as a byte array representing an MMS octet string.</returns>
public byte[] GetEntryId()
{
IntPtr entryIdRef = ClientReport_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();
}
}
}
}
}
}
}

@ -53,11 +53,11 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientSVControlBlock_setSvEna (IntPtr self, bool value);
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_setResv (IntPtr self, bool value);
static extern bool ClientSVControlBlock_setResv (IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]

@ -1,7 +1,7 @@
/*
* TLS.cs
*
* Copyright 2017 Michael Zillgith
* Copyright 2017-2022 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -35,181 +35,400 @@ using IEC61850.Common;
/// </summary>
namespace IEC61850
{
namespace TLS
{
/// <summary>
/// A container for TLS configuration and certificates.
/// </summary>
public class TLSConfiguration : IDisposable
{
private IntPtr self = IntPtr.Zero;
private bool allowOnlyKnownCerts = false;
private bool chainValidation = true;
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr TLSConfiguration_create();
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void TLSConfiguration_destroy(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void TLSConfiguration_setAllowOnlyKnownCertificates(IntPtr self, bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void TLSConfiguration_setChainValidation (IntPtr self, bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void TLSConfiguration_setClientMode(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern bool TLSConfiguration_setOwnCertificate(IntPtr self, byte[] certificate, int certLen);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern bool TLSConfiguration_setOwnCertificateFromFile(IntPtr self, string filename);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern bool TLSConfiguration_setOwnKey(IntPtr self, byte[] key, int keyLen, string keyPassword);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern bool TLSConfiguration_setOwnKeyFromFile (IntPtr self, string filename, string keyPassword);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern bool TLSConfiguration_addAllowedCertificate(IntPtr self, byte[] certificate, int certLen);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern bool TLSConfiguration_addAllowedCertificateFromFile(IntPtr self, string filename);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern bool TLSConfiguration_addCACertificate(IntPtr self, byte[] certificate, int certLen);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern bool TLSConfiguration_addCACertificateFromFile(IntPtr self, string filename);
public TLSConfiguration() {
self = TLSConfiguration_create ();
}
~TLSConfiguration()
{
Dispose ();
}
internal IntPtr GetNativeInstance()
{
return self;
}
public bool AllowOnlyKnownCertificates
{
set {
TLSConfiguration_setAllowOnlyKnownCertificates (self, value);
allowOnlyKnownCerts = value;
}
get {
return allowOnlyKnownCerts;
}
}
public bool ChainValidation
{
set {
TLSConfiguration_setChainValidation (self, value);
chainValidation = value;
}
get {
return chainValidation;
}
}
public void SetClientMode()
{
TLSConfiguration_setClientMode (self);
}
public void SetOwnCertificate(string filename)
{
if (TLSConfiguration_setOwnCertificateFromFile (self, filename) == false) {
Console.WriteLine ("Failed to read certificate from file!");
throw new CryptographicException ("Failed to read certificate from file");
}
}
public void SetOwnCertificate(X509Certificate2 cert)
{
byte[] certBytes = cert.GetRawCertData ();
if (TLSConfiguration_setOwnCertificate (self, certBytes, certBytes.Length) == false) {
Console.WriteLine ("Failed to set certificate!");
throw new CryptographicException ("Failed to set certificate");
}
}
public void AddAllowedCertificate(string filename)
{
if (TLSConfiguration_addAllowedCertificateFromFile (self, filename) == false) {
Console.WriteLine ("Failed to read allowed certificate from file!");
throw new CryptographicException ("Failed to read allowed certificate from file");
}
}
public void AddAllowedCertificate(X509Certificate2 cert)
{
byte[] certBytes = cert.GetRawCertData ();
if (TLSConfiguration_addAllowedCertificate (self, certBytes, certBytes.Length) == false) {
Console.WriteLine ("Failed to add allowed certificate!");
throw new CryptographicException ("Failed to add allowed certificate");
}
}
public void AddCACertificate(string filename)
{
if (TLSConfiguration_addCACertificateFromFile (self, filename) == false) {
Console.WriteLine ("Failed to read CA certificate from file!");
throw new CryptographicException ("Failed to read CA certificate from file");
}
}
public void AddCACertificate(X509Certificate2 cert)
{
byte[] certBytes = cert.GetRawCertData ();
if (TLSConfiguration_addCACertificate (self, certBytes, certBytes.Length) == false) {
Console.WriteLine ("Failed to add CA certificate!");
throw new CryptographicException ("Failed to add CA certificate");
}
}
public void SetOwnKey (string filename, string password)
{
if (TLSConfiguration_setOwnKeyFromFile (self, filename, password) == false) {
Console.WriteLine ("Failed to read own key from file!");
throw new CryptographicException ("Failed to read own key from file");
}
}
public void SetOwnKey (X509Certificate2 key, string password)
{
byte[] certBytes = key.Export (X509ContentType.Pkcs12);
if (TLSConfiguration_setOwnKey (self, certBytes, certBytes.Length, password) == false) {
Console.WriteLine ("Failed to set own key!");
throw new CryptographicException ("Failed to set own key");
}
}
public void Dispose()
{
lock (this) {
if (self != IntPtr.Zero) {
TLSConfiguration_destroy (self);
self = IntPtr.Zero;
}
}
}
}
}
}
namespace TLS
{
public enum TLSConfigVersion
{
NOT_SELECTED = 0,
SSL_3_0 = 3,
TLS_1_0 = 4,
TLS_1_1 = 5,
TLS_1_2 = 6,
TLS_1_3 = 7
}
public enum TLSEventLevel
{
INFO = 0,
WARNING = 1,
INCIDENT = 2
}
public enum TLSEventCode
{
ALM_ALGO_NOT_SUPPORTED = 1,
ALM_UNSECURE_COMMUNICATION = 2,
ALM_CERT_UNAVAILABLE = 3,
ALM_BAD_CERT = 4,
ALM_CERT_SIZE_EXCEEDED = 5,
ALM_CERT_VALIDATION_FAILED = 6,
ALM_CERT_REQUIRED = 7,
ALM_HANDSHAKE_FAILED_UNKNOWN_REASON = 8,
WRN_INSECURE_TLS_VERSION = 9,
INF_SESSION_RENEGOTIATION = 10,
ALM_CERT_EXPIRED = 11,
ALM_CERT_REVOKED = 12,
ALM_CERT_NOT_CONFIGURED = 13,
ALM_CERT_NOT_TRUSTED = 14
}
public class TLSConnection
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int TLSConnection_getTLSVersion(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr TLSConnection_getPeerAddress(IntPtr self, IntPtr peerAddrBuf);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr TLSConnection_getPeerCertificate(IntPtr self, out int certSize);
private IntPtr self;
private bool isValid;
internal TLSConnection(IntPtr self)
{
this.self = self;
isValid = true;
}
// To be called by event callback caller after callback execution
internal void InValidate()
{
lock (this)
{
isValid = false;
}
}
/// <summary>
/// TLS version used by the connection
/// </summary>
public TLSConfigVersion TLSVersion
{
get
{
lock (this)
{
if (isValid)
{
return (TLSConfigVersion)TLSConnection_getTLSVersion((IntPtr)self);
}
else
{
throw new InvalidOperationException("Object cannot be used outside of TLS event callback");
}
}
}
}
/// <summary>
/// Peer IP address and TCP port of the TLS connection
/// </summary>
public string PeerAddress
{
get
{
lock (this)
{
if (isValid)
{
IntPtr peerAddrBuf = Marshal.AllocHGlobal(130);
IntPtr peerAddrStr = TLSConnection_getPeerAddress(this.self, peerAddrBuf);
string peerAddr = null;
if (peerAddrStr != IntPtr.Zero)
{
peerAddr = Marshal.PtrToStringAnsi(peerAddrStr);
}
Marshal.FreeHGlobal(peerAddrBuf);
return peerAddr;
}
else
{
throw new InvalidOperationException("Object cannot be used outside of TLS event callback");
}
}
}
}
/// <summary>
/// TLS certificate used by the peer
/// </summary>
public byte[] PeerCertificate
{
get
{
lock (this)
{
if (isValid)
{
int certSize;
IntPtr certBuffer = TLSConnection_getPeerCertificate(self, out certSize);
if (certBuffer != IntPtr.Zero)
{
if (certSize > 0)
{
byte[] cert = new byte[certSize];
Marshal.Copy(certBuffer, cert, 0, certSize);
return cert;
}
}
return null;
}
else
{
throw new InvalidOperationException("Object cannot be used outside of TLS event callback");
}
}
}
}
}
/// <summary>
/// TLS security event handler
/// </summary>
/// <param name="parameter">user provided context paramter to be passed to the handler</param>
/// <param name="eventLevel">severity level of the event</param>
/// <param name="eventCode">code to identify the event type</param>
/// <param name="message">text message describing the event</param>
/// <param name="connection">TLS connection that caused the event</param>
public delegate void TLSEventHandler(object parameter, TLSEventLevel eventLevel, TLSEventCode eventCode, string message, TLSConnection connection);
/// <summary>
/// A container for TLS configuration and certificates.
/// </summary>
public class TLSConfiguration : IDisposable
{
private IntPtr self = IntPtr.Zero;
private bool allowOnlyKnownCerts = false;
private bool chainValidation = true;
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr TLSConfiguration_create();
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void TLSConfiguration_destroy(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void TLSConfiguration_setAllowOnlyKnownCertificates(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void TLSConfiguration_setChainValidation(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void TLSConfiguration_setClientMode(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool TLSConfiguration_setOwnCertificate(IntPtr self, byte[] certificate, int certLen);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool TLSConfiguration_setOwnCertificateFromFile(IntPtr self, string filename);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool TLSConfiguration_setOwnKey(IntPtr self, byte[] key, int keyLen, string keyPassword);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool TLSConfiguration_setOwnKeyFromFile(IntPtr self, string filename, string keyPassword);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool TLSConfiguration_addAllowedCertificate(IntPtr self, byte[] certificate, int certLen);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool TLSConfiguration_addAllowedCertificateFromFile(IntPtr self, string filename);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool TLSConfiguration_addCACertificate(IntPtr self, byte[] certificate, int certLen);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool TLSConfiguration_addCACertificateFromFile(IntPtr self, string filename);
private TLSEventHandler eventHandler = null;
private object eventHandlerParameter = null;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void InternalTLSEventHandler(IntPtr parameter, int eventLevel, int eventCode, IntPtr message, IntPtr tlsCon);
private InternalTLSEventHandler internalTLSEventHandlerRef = null;
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void TLSConfiguration_setEventHandler(IntPtr self, InternalTLSEventHandler handler, IntPtr parameter);
void InternalTLSEventHandlerImpl(IntPtr parameter, int eventLevel, int eventCode, IntPtr message, IntPtr tlsCon)
{
if (eventHandler != null)
{
TLSConnection connection = new TLSConnection(tlsCon);
string msg = Marshal.PtrToStringAnsi(message);
eventHandler(eventHandlerParameter, (TLSEventLevel)eventLevel, (TLSEventCode)eventCode, msg, connection);
connection.InValidate();
}
}
public void SetEventHandler(TLSEventHandler handler, object parameter)
{
this.eventHandler = handler;
this.eventHandlerParameter = parameter;
if (internalTLSEventHandlerRef == null)
{
internalTLSEventHandlerRef = new InternalTLSEventHandler(InternalTLSEventHandlerImpl);
TLSConfiguration_setEventHandler(self, internalTLSEventHandlerRef, IntPtr.Zero);
}
}
public TLSConfiguration()
{
self = TLSConfiguration_create();
}
~TLSConfiguration()
{
Dispose();
}
internal IntPtr GetNativeInstance()
{
return self;
}
public bool AllowOnlyKnownCertificates
{
set
{
TLSConfiguration_setAllowOnlyKnownCertificates(self, value);
allowOnlyKnownCerts = value;
}
get
{
return allowOnlyKnownCerts;
}
}
public bool ChainValidation
{
set
{
TLSConfiguration_setChainValidation(self, value);
chainValidation = value;
}
get
{
return chainValidation;
}
}
public void SetClientMode()
{
TLSConfiguration_setClientMode(self);
}
public void SetOwnCertificate(string filename)
{
if (TLSConfiguration_setOwnCertificateFromFile(self, filename) == false)
{
throw new CryptographicException("Failed to read certificate from file");
}
}
public void SetOwnCertificate(X509Certificate2 cert)
{
byte[] certBytes = cert.GetRawCertData();
if (TLSConfiguration_setOwnCertificate(self, certBytes, certBytes.Length) == false)
{
throw new CryptographicException("Failed to set certificate");
}
}
public void AddAllowedCertificate(string filename)
{
if (TLSConfiguration_addAllowedCertificateFromFile(self, filename) == false)
{
throw new CryptographicException("Failed to read allowed certificate from file");
}
}
public void AddAllowedCertificate(X509Certificate2 cert)
{
byte[] certBytes = cert.GetRawCertData();
if (TLSConfiguration_addAllowedCertificate(self, certBytes, certBytes.Length) == false)
{
throw new CryptographicException("Failed to add allowed certificate");
}
}
public void AddCACertificate(string filename)
{
if (TLSConfiguration_addCACertificateFromFile(self, filename) == false)
{
throw new CryptographicException("Failed to read CA certificate from file");
}
}
public void AddCACertificate(X509Certificate2 cert)
{
byte[] certBytes = cert.GetRawCertData();
if (TLSConfiguration_addCACertificate(self, certBytes, certBytes.Length) == false)
{
throw new CryptographicException("Failed to add CA certificate");
}
}
public void SetOwnKey(string filename, string password)
{
if (TLSConfiguration_setOwnKeyFromFile(self, filename, password) == false)
{
throw new CryptographicException("Failed to read own key from file");
}
}
public void SetOwnKey(X509Certificate2 key, string password)
{
byte[] certBytes = key.Export(X509ContentType.Pkcs12);
if (TLSConfiguration_setOwnKey(self, certBytes, certBytes.Length, password) == false)
{
throw new CryptographicException("Failed to set own key");
}
}
public void Dispose()
{
lock (this)
{
if (self != IntPtr.Zero)
{
TLSConfiguration_destroy(self);
self = IntPtr.Zero;
}
}
}
}
}
}

@ -0,0 +1,187 @@
using System;
using IEC61850.Client;
using IEC61850.Common;
using System.Threading;
using System.Collections.Generic;
namespace client_example_async
{
class MainClass
{
public static void Main (string[] args)
{
IedConnection con = new IedConnection ();
string hostname;
if (args.Length > 0)
hostname = args[0];
else
hostname = "127.0.0.1";
int port = 102;
if (args.Length > 1)
port = Int32.Parse(args [1]);
Console.WriteLine("Connect to " + hostname);
try
{
con.MaxPduSize = 1000;
con.StateChanged = delegate(IedConnection connection, IedConnectionState newState) {
Console.WriteLine("state change: " + newState.ToString());
};
con.Connect(hostname, port);
AutoResetEvent waitForCallback = new AutoResetEvent(false);
List<string> ldList = null;
con.GetServerDirectoryAsync(ldList, null, delegate(uint invokeId, object parameter, IedClientError err, System.Collections.Generic.List<string> nameList, bool moreFollows) {
if (nameList != null) {
ldList = nameList;
}
else
{
Console.WriteLine("Get server directory error: " + err.ToString());
}
waitForCallback.Set();
}, null);
waitForCallback.WaitOne();
if (ldList != null) {
string firstLdName = null;
Console.WriteLine("Server directory:");
foreach (string ldName in ldList) {
Console.WriteLine(" LD: " + ldName);
if (firstLdName == null)
firstLdName = ldName;
}
bool moreVariabesFollows = true;
string lastVariableName = null;
List<string> variablesList = new List<string>();
while (moreVariabesFollows) {
waitForCallback.Reset();
con.GetLogicalDeviceVariablesAsync(variablesList, firstLdName, lastVariableName, delegate(uint invokeId, object parameter, IedClientError err, List<string> nameList, bool moreFollows) {
if (nameList != null) {
if (moreFollows)
Console.WriteLine("More variables available...");
lastVariableName = nameList[nameList.Count - 1];
}
else
{
Console.WriteLine("Get logical device variables error: " + err.ToString());
}
moreVariabesFollows = moreFollows;
waitForCallback.Set();
}, null);
waitForCallback.WaitOne();
}
Console.WriteLine("Variables in logical device {0}:", firstLdName);
foreach (string variableName in variablesList) {
Console.WriteLine(" {0}", variableName);
}
}
Console.WriteLine("Now read variables...");
/* read FCDO */
con.ReadValueAsync("simpleIOGenericIO/GGIO1.AnIn1", FunctionalConstraint.MX, delegate(uint invokeId, object parameter, IedClientError err, MmsValue value) {
if (err == IedClientError.IED_ERROR_OK)
{
if (value.GetType() == MmsType.MMS_STRUCTURE)
{
Console.WriteLine("Value is of complex type");
for (int i = 0; i < value.Size(); i++)
{
Console.WriteLine(" element: " + value.GetElement(i).GetType());
if (value.GetElement(i).GetType() == MmsType.MMS_UTC_TIME)
{
Console.WriteLine(" -> " + value.GetElement(i).GetUtcTimeAsDateTimeOffset());
}
}
}
}
else {
Console.WriteLine("Read error: " + err.ToString());
}
}, null);
con.ReadValueAsync("simpleIOGenericIO/GGIO1.AnIn1", FunctionalConstraint.MX, delegate(uint invokeId, object parameter, IedClientError err, MmsValue value) {
if (err == IedClientError.IED_ERROR_OK)
{
if (value.GetType() == MmsType.MMS_STRUCTURE)
{
Console.WriteLine("Value is of complex type");
for (int i = 0; i < value.Size(); i++)
{
Console.WriteLine(" element: " + value.GetElement(i).GetType());
if (value.GetElement(i).GetType() == MmsType.MMS_UTC_TIME)
{
Console.WriteLine(" -> " + value.GetElement(i).GetUtcTimeAsDateTimeOffset());
}
}
}
}
else {
Console.WriteLine("Read error: " + err.ToString());
}
}, null);
Thread.Sleep(5000);
con.Abort();
Console.WriteLine("Aborted");
}
catch (IedConnectionException e)
{
Console.WriteLine(e.Message);
}
System.Threading.Thread.Sleep(2000);
// release all resources - do NOT use the object after this call!!
con.Dispose ();
}
static void HandleReadObjectHandler (uint invokeId, object parameter, IedClientError err, MmsValue value)
{
}
}
}

@ -0,0 +1,27 @@
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.
//[assembly: AssemblyDelaySign(false)]
//[assembly: AssemblyKeyFile("")]

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{71902641-776A-47D8-9C0E-9ACBBEAC1370}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>client_example_async</RootNamespace>
<AssemblyName>client_example_async</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile />
</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" />
</ItemGroup>
</Project>

@ -0,0 +1,78 @@
using System;
using IEC61850.Client;
using IEC61850.Common;
namespace client_examples_setting_groups
{
/// <summary>
/// This class is intended to show how to use setting groups from the client side.
/// It works with server_example_setting_groups.
/// </summary>
class SettingGroupsClientExample
{
public static void Main(string[] args)
{
Console.WriteLine("Hello World!");
IedConnection con = new IedConnection ();
string hostname;
if (args.Length > 0)
hostname = args[0];
else
hostname = "127.0.0.1";
int port = 102;
if (args.Length > 1)
port = Int32.Parse(args [1]);
Console.WriteLine("Connect to " + hostname);
try
{
con.Connect(hostname, port);
/* Get variable specification of the SGCB (optional) */
MmsVariableSpecification sgcbVarSpec = con.GetVariableSpecification("DEMOPROT/LLN0.SGCB", FunctionalConstraint.SP);
/* Read SGCB */
MmsValue sgcbVal = con.ReadValue("DEMOPROT/LLN0.SGCB", FunctionalConstraint.SP);
Console.WriteLine("NumOfSG: {0}", sgcbVal.GetChildValue("NumOfSG", sgcbVarSpec).ToString());
Console.WriteLine("ActSG: {0}", sgcbVal.GetChildValue("ActSG", sgcbVarSpec).ToString());
Console.WriteLine("EditSG: {0}", sgcbVal.GetChildValue("EditSG", sgcbVarSpec).ToString());
Console.WriteLine("CnfEdit: {0}", sgcbVal.GetChildValue("CnfEdit", sgcbVarSpec).ToString());
/* Set active setting group */
con.WriteValue("DEMOPROT/LLN0.SGCB.ActSG", FunctionalConstraint.SP, new MmsValue((uint) 2));
/* Set edit setting group */
con.WriteValue("DEMOPROT/LLN0.SGCB.EditSG", FunctionalConstraint.SP, new MmsValue((uint) 1));
/* Change a setting group value */
con.WriteValue("DEMOPROT/PTOC1.StrVal.setMag.f", FunctionalConstraint.SE, new MmsValue(1.0f));
/* Confirm new setting group values */
con.WriteValue("DEMOPROT/LLN0.SGCB.CnfEdit", FunctionalConstraint.SP, new MmsValue(true));
/* Read SGCB again */
sgcbVal = con.ReadValue("DEMOPROT/LLN0.SGCB", FunctionalConstraint.SP);
Console.WriteLine("ActSG: {0}",sgcbVal.GetChildValue("ActSG", sgcbVarSpec).ToString());
con.Abort();
}
catch (IedConnectionException e)
{
Console.WriteLine(e.Message);
}
// release all resources - do NOT use the object after this call!!
con.Dispose ();
}
}
}

@ -0,0 +1,27 @@
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.
//[assembly: AssemblyDelaySign(false)]
//[assembly: AssemblyKeyFile("")]

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{0DA95476-B149-450B-AC36-01CEECFC1A43}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>clientexamplesettinggroup</RootNamespace>
<AssemblyName>client-example-setting-group</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</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>
</ItemGroup>
</Project>

@ -40,6 +40,7 @@ namespace control
ControlModel controlModel = control.GetControlModel();
Console.WriteLine(objectReference + " has control model " + controlModel.ToString());
Console.WriteLine(" type of ctlVal: " + control.GetCtlValType().ToString());
switch (controlModel) {

@ -0,0 +1,109 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2010
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IEC61850.NET.core.2.0", "IEC61850.NET.core.2.0\IEC61850.NET.core.2.0.csproj", "{16C58017-94CC-4C92-AFDC-84AC24C393AD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client_example1", "client_example1\client_example1.csproj", "{AFDC261C-B293-4650-8D90-A862E27CEC15}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client_example2", "client_example2\client_example2.csproj", "{4FD69E0A-2548-4BFF-BD15-7ED0612C2FC1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client_example3", "client_example3\client_example3.csproj", "{11B5EE5D-36AC-4DAD-89E5-251E46A6269E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client_example_files", "client_example_files\client_example_files.csproj", "{3B0970E6-77A3-4D97-A998-50758BE7C4DC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client_example_datasets", "client_example_datasets\client_example_datasets.csproj", "{F61DD20F-4CF4-49FD-836A-AA233B4659B8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client_example_control", "client_example_control\client_example_control.csproj", "{53FF9ABD-300B-49F2-80A6-15B98121066D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client_example_authenticate", "client_example_authenticate\client_example_authenticate.csproj", "{6E85A44B-E29D-4819-8AF6-2CEAD7851C1B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client_example_reporting", "client_example_reporting\client_example_reporting.csproj", "{BA077BC8-0B98-4071-8F1F-C97865954477}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client_example_tls", "client_example_tls\client_example_tls.csproj", "{954CCB43-3640-48F1-9A8E-4D736A5EF575}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client_example_model_browsing", "client_example_model_browsing\client_example_model_browsing.csproj", "{A9890431-ABE4-4D80-8D36-132E4096E163}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "server_example1", "server_example1\server_example1.csproj", "{18A97E35-2FF9-49F7-934F-F1E9C50DC054}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "sv_subscriber_example", "sv_subscriber_example\sv_subscriber_example.csproj", "{D9D8B1B7-B4CB-473D-9C6C-3B2F3C4DB2BD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "goose_subscriber_example", "goose_subscriber_example\goose_subscriber_example.csproj", "{ABBF5A82-4F5E-41DA-A727-C2298E8AF650}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client_example_log", "client_example_log\client_example_log.csproj", "{160586BB-3601-4D0C-86D7-414F585041B4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{16C58017-94CC-4C92-AFDC-84AC24C393AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{16C58017-94CC-4C92-AFDC-84AC24C393AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{16C58017-94CC-4C92-AFDC-84AC24C393AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{16C58017-94CC-4C92-AFDC-84AC24C393AD}.Release|Any CPU.Build.0 = Release|Any CPU
{AFDC261C-B293-4650-8D90-A862E27CEC15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AFDC261C-B293-4650-8D90-A862E27CEC15}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AFDC261C-B293-4650-8D90-A862E27CEC15}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AFDC261C-B293-4650-8D90-A862E27CEC15}.Release|Any CPU.Build.0 = Release|Any CPU
{4FD69E0A-2548-4BFF-BD15-7ED0612C2FC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4FD69E0A-2548-4BFF-BD15-7ED0612C2FC1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4FD69E0A-2548-4BFF-BD15-7ED0612C2FC1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4FD69E0A-2548-4BFF-BD15-7ED0612C2FC1}.Release|Any CPU.Build.0 = Release|Any CPU
{11B5EE5D-36AC-4DAD-89E5-251E46A6269E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{11B5EE5D-36AC-4DAD-89E5-251E46A6269E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{11B5EE5D-36AC-4DAD-89E5-251E46A6269E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{11B5EE5D-36AC-4DAD-89E5-251E46A6269E}.Release|Any CPU.Build.0 = Release|Any CPU
{3B0970E6-77A3-4D97-A998-50758BE7C4DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3B0970E6-77A3-4D97-A998-50758BE7C4DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3B0970E6-77A3-4D97-A998-50758BE7C4DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3B0970E6-77A3-4D97-A998-50758BE7C4DC}.Release|Any CPU.Build.0 = Release|Any CPU
{F61DD20F-4CF4-49FD-836A-AA233B4659B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F61DD20F-4CF4-49FD-836A-AA233B4659B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F61DD20F-4CF4-49FD-836A-AA233B4659B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F61DD20F-4CF4-49FD-836A-AA233B4659B8}.Release|Any CPU.Build.0 = Release|Any CPU
{53FF9ABD-300B-49F2-80A6-15B98121066D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{53FF9ABD-300B-49F2-80A6-15B98121066D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{53FF9ABD-300B-49F2-80A6-15B98121066D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{53FF9ABD-300B-49F2-80A6-15B98121066D}.Release|Any CPU.Build.0 = Release|Any CPU
{6E85A44B-E29D-4819-8AF6-2CEAD7851C1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6E85A44B-E29D-4819-8AF6-2CEAD7851C1B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6E85A44B-E29D-4819-8AF6-2CEAD7851C1B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6E85A44B-E29D-4819-8AF6-2CEAD7851C1B}.Release|Any CPU.Build.0 = Release|Any CPU
{BA077BC8-0B98-4071-8F1F-C97865954477}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BA077BC8-0B98-4071-8F1F-C97865954477}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BA077BC8-0B98-4071-8F1F-C97865954477}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BA077BC8-0B98-4071-8F1F-C97865954477}.Release|Any CPU.Build.0 = Release|Any CPU
{954CCB43-3640-48F1-9A8E-4D736A5EF575}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{954CCB43-3640-48F1-9A8E-4D736A5EF575}.Debug|Any CPU.Build.0 = Debug|Any CPU
{954CCB43-3640-48F1-9A8E-4D736A5EF575}.Release|Any CPU.ActiveCfg = Release|Any CPU
{954CCB43-3640-48F1-9A8E-4D736A5EF575}.Release|Any CPU.Build.0 = Release|Any CPU
{A9890431-ABE4-4D80-8D36-132E4096E163}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A9890431-ABE4-4D80-8D36-132E4096E163}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A9890431-ABE4-4D80-8D36-132E4096E163}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A9890431-ABE4-4D80-8D36-132E4096E163}.Release|Any CPU.Build.0 = Release|Any CPU
{18A97E35-2FF9-49F7-934F-F1E9C50DC054}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{18A97E35-2FF9-49F7-934F-F1E9C50DC054}.Debug|Any CPU.Build.0 = Debug|Any CPU
{18A97E35-2FF9-49F7-934F-F1E9C50DC054}.Release|Any CPU.ActiveCfg = Release|Any CPU
{18A97E35-2FF9-49F7-934F-F1E9C50DC054}.Release|Any CPU.Build.0 = Release|Any CPU
{D9D8B1B7-B4CB-473D-9C6C-3B2F3C4DB2BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D9D8B1B7-B4CB-473D-9C6C-3B2F3C4DB2BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D9D8B1B7-B4CB-473D-9C6C-3B2F3C4DB2BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D9D8B1B7-B4CB-473D-9C6C-3B2F3C4DB2BD}.Release|Any CPU.Build.0 = Release|Any CPU
{ABBF5A82-4F5E-41DA-A727-C2298E8AF650}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ABBF5A82-4F5E-41DA-A727-C2298E8AF650}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ABBF5A82-4F5E-41DA-A727-C2298E8AF650}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ABBF5A82-4F5E-41DA-A727-C2298E8AF650}.Release|Any CPU.Build.0 = Release|Any CPU
{160586BB-3601-4D0C-86D7-414F585041B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{160586BB-3601-4D0C-86D7-414F585041B4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{160586BB-3601-4D0C-86D7-414F585041B4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{160586BB-3601-4D0C-86D7-414F585041B4}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BE4487ED-D36A-438B-B1EF-BC3CA409D4BF}
EndGlobalSection
EndGlobal

@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\..\..\IEC61850forCSharp\Control.cs" Link="Control.cs" />
<Compile Include="..\..\..\IEC61850forCSharp\DataSet.cs" Link="DataSet.cs" />
<Compile Include="..\..\..\IEC61850forCSharp\GooseControlBlock.cs" Link="GooseControlBlock.cs" />
<Compile Include="..\..\..\IEC61850forCSharp\GooseSubscriber.cs" Link="GooseSubscriber.cs" />
<Compile Include="..\..\..\IEC61850forCSharp\IEC61850ClientAPI.cs" Link="IEC61850ClientAPI.cs" />
<Compile Include="..\..\..\IEC61850forCSharp\IEC61850CommonAPI.cs" Link="IEC61850CommonAPI.cs" />
<Compile Include="..\..\..\IEC61850forCSharp\IEC61850ServerAPI.cs" Link="IEC61850ServerAPI.cs" />
<Compile Include="..\..\..\IEC61850forCSharp\IedServerConfig.cs" Link="IedServerConfig.cs" />
<Compile Include="..\..\..\IEC61850forCSharp\IsoConnectionParameters.cs" Link="IsoConnectionParameters.cs" />
<Compile Include="..\..\..\IEC61850forCSharp\MmsValue.cs" Link="MmsValue.cs" />
<Compile Include="..\..\..\IEC61850forCSharp\MmsVariableSpecification.cs" Link="MmsVariableSpecification.cs" />
<Compile Include="..\..\..\IEC61850forCSharp\ReportControlBlock.cs" Link="ReportControlBlock.cs" />
<Compile Include="..\..\..\IEC61850forCSharp\Reporting.cs" Link="Reporting.cs" />
<Compile Include="..\..\..\IEC61850forCSharp\SampledValuesControlBlock.cs" Link="SampledValuesControlBlock.cs" />
<Compile Include="..\..\..\IEC61850forCSharp\SampledValuesSubscriber.cs" Link="SampledValuesSubscriber.cs" />
<Compile Include="..\..\..\IEC61850forCSharp\TLS.cs" Link="TLS.cs" />
</ItemGroup>
</Project>

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\..\..\example1\Main.cs" Link="Main.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IEC61850.NET.core.2.0\IEC61850.NET.core.2.0.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\..\..\example2\WriteValueExample.cs" Link="WriteValueExample.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IEC61850.NET.core.2.0\IEC61850.NET.core.2.0.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\..\..\example3\Main.cs" Link="Main.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IEC61850.NET.core.2.0\IEC61850.NET.core.2.0.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\..\..\authenticate\Main.cs" Link="Main.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IEC61850.NET.core.2.0\IEC61850.NET.core.2.0.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\..\..\control\ControlExample.cs" Link="ControlExample.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IEC61850.NET.core.2.0\IEC61850.NET.core.2.0.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\..\..\datasets\DataSetExample.cs" Link="DataSetExample.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IEC61850.NET.core.2.0\IEC61850.NET.core.2.0.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\..\..\files\FileServicesExample.cs" Link="FileServicesExample.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IEC61850.NET.core.2.0\IEC61850.NET.core.2.0.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\..\..\log_client\Program.cs" Link="Program.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IEC61850.NET.core.2.0\IEC61850.NET.core.2.0.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\..\..\model_browsing\ModelBrowsing.cs" Link="ModelBrowsing.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IEC61850.NET.core.2.0\IEC61850.NET.core.2.0.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\..\..\reporting\ReportingExample.cs" Link="ReportingExample.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IEC61850.NET.core.2.0\IEC61850.NET.core.2.0.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\..\..\tls_client_example\Program.cs" Link="Program.cs" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\..\tls_client_example\client1-key.pem" Link="client1-key.pem">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="..\..\..\tls_client_example\client1.cer" Link="client1.cer">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="..\..\..\tls_client_example\root.cer" Link="root.cer">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IEC61850.NET.core.2.0\IEC61850.NET.core.2.0.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\..\..\goose_subscriber\Program.cs" Link="Program.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IEC61850.NET.core.2.0\IEC61850.NET.core.2.0.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\..\..\server1\Program.cs" Link="Program.cs" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\..\server1\model.cfg" Link="model.cfg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IEC61850.NET.core.2.0\IEC61850.NET.core.2.0.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\..\..\sv_subscriber\Program.cs" Link="Program.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IEC61850.NET.core.2.0\IEC61850.NET.core.2.0.csproj" />
</ItemGroup>
</Project>

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
VisualStudioVersion = 12.0.40629.0
# Visual Studio 15
VisualStudioVersion = 15.0.28307.779
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IEC61850.NET", "IEC61850forCSharp\IEC61850.NET.csproj", "{C35D624E-5506-4560-8074-1728F1FA1A4D}"
EndProject
@ -42,64 +42,20 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "goose_subscriber", "goose_s
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "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}"
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}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "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}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0BECEC77-2315-4B95-AFF9-E6007E644BBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0BECEC77-2315-4B95-AFF9-E6007E644BBF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0BECEC77-2315-4B95-AFF9-E6007E644BBF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0BECEC77-2315-4B95-AFF9-E6007E644BBF}.Release|Any CPU.Build.0 = Release|Any CPU
{1285372C-2E62-494A-A661-8D5D3873318C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1285372C-2E62-494A-A661-8D5D3873318C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1285372C-2E62-494A-A661-8D5D3873318C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1285372C-2E62-494A-A661-8D5D3873318C}.Release|Any CPU.Build.0 = Release|Any CPU
{14C71267-2F38-460D-AA55-6803EE80AFB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{14C71267-2F38-460D-AA55-6803EE80AFB4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{14C71267-2F38-460D-AA55-6803EE80AFB4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{14C71267-2F38-460D-AA55-6803EE80AFB4}.Release|Any CPU.Build.0 = Release|Any CPU
{2A226B6D-1D1F-4BFE-B8CC-158116F71270}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2A226B6D-1D1F-4BFE-B8CC-158116F71270}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2A226B6D-1D1F-4BFE-B8CC-158116F71270}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2A226B6D-1D1F-4BFE-B8CC-158116F71270}.Release|Any CPU.Build.0 = Release|Any CPU
{44651D2D-3252-4FD5-8B8B-5552DBE1B499}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{44651D2D-3252-4FD5-8B8B-5552DBE1B499}.Debug|Any CPU.Build.0 = Debug|Any CPU
{44651D2D-3252-4FD5-8B8B-5552DBE1B499}.Release|Any CPU.ActiveCfg = Release|Any CPU
{44651D2D-3252-4FD5-8B8B-5552DBE1B499}.Release|Any CPU.Build.0 = Release|Any CPU
{59B85486-F48D-4978-BD35-8F5C3A8288D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{59B85486-F48D-4978-BD35-8F5C3A8288D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{59B85486-F48D-4978-BD35-8F5C3A8288D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{59B85486-F48D-4978-BD35-8F5C3A8288D4}.Release|Any CPU.Build.0 = Release|Any CPU
{5E5D0FE0-DF44-48D8-A10E-1FB07D34DEA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5E5D0FE0-DF44-48D8-A10E-1FB07D34DEA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5E5D0FE0-DF44-48D8-A10E-1FB07D34DEA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5E5D0FE0-DF44-48D8-A10E-1FB07D34DEA2}.Release|Any CPU.Build.0 = Release|Any CPU
{6734BF52-2D0D-476B-8EA2-C9C2D1D69B03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6734BF52-2D0D-476B-8EA2-C9C2D1D69B03}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6734BF52-2D0D-476B-8EA2-C9C2D1D69B03}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6734BF52-2D0D-476B-8EA2-C9C2D1D69B03}.Release|Any CPU.Build.0 = Release|Any CPU
{71485F99-2976-45E6-B73D-4946E594C15C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{71485F99-2976-45E6-B73D-4946E594C15C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{71485F99-2976-45E6-B73D-4946E594C15C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{71485F99-2976-45E6-B73D-4946E594C15C}.Release|Any CPU.Build.0 = Release|Any CPU
{77127456-19B9-4D1A-AEF9-40F8D1C5695E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{77127456-19B9-4D1A-AEF9-40F8D1C5695E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{77127456-19B9-4D1A-AEF9-40F8D1C5695E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{77127456-19B9-4D1A-AEF9-40F8D1C5695E}.Release|Any CPU.Build.0 = Release|Any CPU
{9286D2AB-96ED-4631-AB3C-ED20FF5D6E6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9286D2AB-96ED-4631-AB3C-ED20FF5D6E6C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9286D2AB-96ED-4631-AB3C-ED20FF5D6E6C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9286D2AB-96ED-4631-AB3C-ED20FF5D6E6C}.Release|Any CPU.Build.0 = Release|Any CPU
{9E29B4CE-EE5F-4CA6-85F6-5D1FF8B27BF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9E29B4CE-EE5F-4CA6-85F6-5D1FF8B27BF8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9E29B4CE-EE5F-4CA6-85F6-5D1FF8B27BF8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9E29B4CE-EE5F-4CA6-85F6-5D1FF8B27BF8}.Release|Any CPU.Build.0 = Release|Any CPU
{C351CFA4-E54E-49A1-86CE-69643535541A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C351CFA4-E54E-49A1-86CE-69643535541A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C351CFA4-E54E-49A1-86CE-69643535541A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C351CFA4-E54E-49A1-86CE-69643535541A}.Release|Any CPU.Build.0 = Release|Any CPU
{C35D624E-5506-4560-8074-1728F1FA1A4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C35D624E-5506-4560-8074-1728F1FA1A4D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C35D624E-5506-4560-8074-1728F1FA1A4D}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -108,16 +64,88 @@ Global
{C616A6DF-831E-443C-9310-3F343A6E3D1A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C616A6DF-831E-443C-9310-3F343A6E3D1A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C616A6DF-831E-443C-9310-3F343A6E3D1A}.Release|Any CPU.Build.0 = Release|Any CPU
{59B85486-F48D-4978-BD35-8F5C3A8288D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{59B85486-F48D-4978-BD35-8F5C3A8288D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{59B85486-F48D-4978-BD35-8F5C3A8288D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{59B85486-F48D-4978-BD35-8F5C3A8288D4}.Release|Any CPU.Build.0 = Release|Any CPU
{D5C7DD38-032A-49B6-B74F-FFD9724A8AE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D5C7DD38-032A-49B6-B74F-FFD9724A8AE4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D5C7DD38-032A-49B6-B74F-FFD9724A8AE4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D5C7DD38-032A-49B6-B74F-FFD9724A8AE4}.Release|Any CPU.Build.0 = Release|Any CPU
{C351CFA4-E54E-49A1-86CE-69643535541A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C351CFA4-E54E-49A1-86CE-69643535541A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C351CFA4-E54E-49A1-86CE-69643535541A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C351CFA4-E54E-49A1-86CE-69643535541A}.Release|Any CPU.Build.0 = Release|Any CPU
{9E29B4CE-EE5F-4CA6-85F6-5D1FF8B27BF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9E29B4CE-EE5F-4CA6-85F6-5D1FF8B27BF8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9E29B4CE-EE5F-4CA6-85F6-5D1FF8B27BF8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9E29B4CE-EE5F-4CA6-85F6-5D1FF8B27BF8}.Release|Any CPU.Build.0 = Release|Any CPU
{2A226B6D-1D1F-4BFE-B8CC-158116F71270}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2A226B6D-1D1F-4BFE-B8CC-158116F71270}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2A226B6D-1D1F-4BFE-B8CC-158116F71270}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2A226B6D-1D1F-4BFE-B8CC-158116F71270}.Release|Any CPU.Build.0 = Release|Any CPU
{0BECEC77-2315-4B95-AFF9-E6007E644BBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0BECEC77-2315-4B95-AFF9-E6007E644BBF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0BECEC77-2315-4B95-AFF9-E6007E644BBF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0BECEC77-2315-4B95-AFF9-E6007E644BBF}.Release|Any CPU.Build.0 = Release|Any CPU
{FBDFE530-DBEB-474B-BA54-9AB287DD57B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FBDFE530-DBEB-474B-BA54-9AB287DD57B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FBDFE530-DBEB-474B-BA54-9AB287DD57B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FBDFE530-DBEB-474B-BA54-9AB287DD57B3}.Release|Any CPU.Build.0 = Release|Any CPU
{77127456-19B9-4D1A-AEF9-40F8D1C5695E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{77127456-19B9-4D1A-AEF9-40F8D1C5695E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{77127456-19B9-4D1A-AEF9-40F8D1C5695E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{77127456-19B9-4D1A-AEF9-40F8D1C5695E}.Release|Any CPU.Build.0 = Release|Any CPU
{5E5D0FE0-DF44-48D8-A10E-1FB07D34DEA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5E5D0FE0-DF44-48D8-A10E-1FB07D34DEA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5E5D0FE0-DF44-48D8-A10E-1FB07D34DEA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5E5D0FE0-DF44-48D8-A10E-1FB07D34DEA2}.Release|Any CPU.Build.0 = Release|Any CPU
{71485F99-2976-45E6-B73D-4946E594C15C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{71485F99-2976-45E6-B73D-4946E594C15C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{71485F99-2976-45E6-B73D-4946E594C15C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{71485F99-2976-45E6-B73D-4946E594C15C}.Release|Any CPU.Build.0 = Release|Any CPU
{14C71267-2F38-460D-AA55-6803EE80AFB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{14C71267-2F38-460D-AA55-6803EE80AFB4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{14C71267-2F38-460D-AA55-6803EE80AFB4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{14C71267-2F38-460D-AA55-6803EE80AFB4}.Release|Any CPU.Build.0 = Release|Any CPU
{9286D2AB-96ED-4631-AB3C-ED20FF5D6E6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9286D2AB-96ED-4631-AB3C-ED20FF5D6E6C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9286D2AB-96ED-4631-AB3C-ED20FF5D6E6C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9286D2AB-96ED-4631-AB3C-ED20FF5D6E6C}.Release|Any CPU.Build.0 = Release|Any CPU
{6734BF52-2D0D-476B-8EA2-C9C2D1D69B03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6734BF52-2D0D-476B-8EA2-C9C2D1D69B03}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6734BF52-2D0D-476B-8EA2-C9C2D1D69B03}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6734BF52-2D0D-476B-8EA2-C9C2D1D69B03}.Release|Any CPU.Build.0 = Release|Any CPU
{1285372C-2E62-494A-A661-8D5D3873318C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1285372C-2E62-494A-A661-8D5D3873318C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1285372C-2E62-494A-A661-8D5D3873318C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1285372C-2E62-494A-A661-8D5D3873318C}.Release|Any CPU.Build.0 = Release|Any CPU
{44651D2D-3252-4FD5-8B8B-5552DBE1B499}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{44651D2D-3252-4FD5-8B8B-5552DBE1B499}.Debug|Any CPU.Build.0 = Debug|Any CPU
{44651D2D-3252-4FD5-8B8B-5552DBE1B499}.Release|Any CPU.ActiveCfg = Release|Any CPU
{44651D2D-3252-4FD5-8B8B-5552DBE1B499}.Release|Any CPU.Build.0 = Release|Any CPU
{B63F7A81-1D3A-4F2F-A7C2-D6F77E5BD307}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B63F7A81-1D3A-4F2F-A7C2-D6F77E5BD307}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B63F7A81-1D3A-4F2F-A7C2-D6F77E5BD307}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B63F7A81-1D3A-4F2F-A7C2-D6F77E5BD307}.Release|Any CPU.Build.0 = Release|Any CPU
{0DA95476-B149-450B-AC36-01CEECFC1A43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0DA95476-B149-450B-AC36-01CEECFC1A43}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0DA95476-B149-450B-AC36-01CEECFC1A43}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0DA95476-B149-450B-AC36-01CEECFC1A43}.Release|Any CPU.Build.0 = Release|Any CPU
{71902641-776A-47D8-9C0E-9ACBBEAC1370}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{71902641-776A-47D8-9C0E-9ACBBEAC1370}.Debug|Any CPU.Build.0 = Debug|Any CPU
{71902641-776A-47D8-9C0E-9ACBBEAC1370}.Release|Any CPU.ActiveCfg = Release|Any CPU
{71902641-776A-47D8-9C0E-9ACBBEAC1370}.Release|Any CPU.Build.0 = Release|Any CPU
{C14BB883-86B8-401C-B3D6-B655F55F3298}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{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
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {9F590B86-C80C-4658-83BC-855A87751CEF}
EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution
Policies = $0
@ -131,7 +159,4 @@ Global
$2.inheritsScope = text/plain
StartupItem = IEC61850forCSharp\IEC61850forCSharp.csproj
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

@ -67,7 +67,18 @@ namespace example1
DataSet dataSet = con.ReadDataSetValues("simpleIOGenericIO/LLN0.Events", null);
Console.WriteLine("Read data set " + dataSet.GetReference());
Console.WriteLine("Read data set " + dataSet.GetReference());
/* read multiple variables (WARNING: this is not IEC 61850 standard compliant but might
* be supported by most servers).
*/
MmsConnection mmsConnection = con.GetMmsConnection();
MmsValue result = mmsConnection.ReadMultipleVariables("simpleIOGenericIO", new List<string>() {
"GGIO1$ST$Ind1", "GGIO1$ST$Ind1", "GGIO1$ST$Ind1","GGIO1$ST$Ind1"
});
Console.WriteLine(result.ToString());
con.Abort();
}

@ -24,11 +24,11 @@ namespace example3
{
IsoConnectionParameters parameters = con.GetConnectionParameters();
parameters.SetRemoteAddresses(1, new byte[] {0x00, 0x01}, new byte[] {0x00, 0x01, 0x02, 0x03});
parameters.SetRemoteAddresses(new byte[] { 0x00, 0x01 }, new byte[] {0x00, 0x01}, new byte[] {0x00, 0x01, 0x02, 0x03});
con.ConnectTimeout = 10000;
con.GetMmsConnection().SetLocalDetail(1200);
con.MaxPduSize = 1200;
con.Connect(hostname, 102);

@ -4,48 +4,58 @@ using System.Collections.Generic;
using IEC61850.Client;
using IEC61850.Common;
using System.IO;
using System.Threading;
namespace files
{
class MainClass
{
public static void printFiles (IedConnection con, string prefix, string parent)
{
List<FileDirectoryEntry> files = con.GetFileDirectory (parent);
foreach (FileDirectoryEntry file in files) {
Console.WriteLine(prefix + file.GetFileName() + "\t" + file.GetFileSize() + "\t" +
MmsValue.MsTimeToDateTimeOffset(file.GetLastModified()));
if (file.GetFileName().EndsWith("/")) {
printFiles (con, prefix + " ", parent + file.GetFileName());
}
}
/// <summary>
/// This example connects to an IEC 61850 device, list the available files, and then
/// tries to read the file "IEDSERVER.BIN" from the server.
/// </summary>
class MainClass
{
public static void printFiles(IedConnection con, string prefix, string parent)
{
bool moreFollows = false;
List<FileDirectoryEntry> files = con.GetFileDirectoryEx(parent, null, out moreFollows);
foreach (FileDirectoryEntry file in files)
{
Console.WriteLine(prefix + file.GetFileName() + "\t" + file.GetFileSize() + "\t" +
MmsValue.MsTimeToDateTimeOffset(file.GetLastModified()));
}
if (file.GetFileName().EndsWith("/"))
{
printFiles(con, prefix + " ", parent + file.GetFileName());
}
}
static bool getFileHandler (object parameter, byte[] data)
{
Console.WriteLine("received " + data.Length + " bytes");
if (moreFollows)
Console.WriteLine("-- MORE FILES AVAILABLE --");
}
BinaryWriter binWriter = (BinaryWriter) parameter;
static bool getFileHandler(object parameter, byte[] data)
{
Console.WriteLine("received " + data.Length + " bytes");
binWriter.Write(data);
BinaryWriter binWriter = (BinaryWriter)parameter;
return true;
}
binWriter.Write(data);
return true;
}
public static void Main (string[] args)
{
IedConnection con = new IedConnection ();
public static void Main(string[] args)
{
IedConnection con = new IedConnection();
string hostname;
if (args.Length > 0)
hostname = args[0];
else
hostname = "10.0.2.2";
hostname = "127.0.0.1";
Console.WriteLine("Connect to " + hostname);
@ -53,40 +63,72 @@ namespace files
{
con.Connect(hostname, 102);
Console.WriteLine ("Files in server root directory:");
Console.WriteLine("Files in server root directory:");
List<string> serverDirectory = con.GetServerDirectory(true);
foreach (string entry in serverDirectory) {
Console.WriteLine(entry);
}
foreach (string entry in serverDirectory)
{
Console.WriteLine(entry);
}
Console.WriteLine();
Console.WriteLine("File directory tree at server:");
printFiles(con, "", "");
Console.WriteLine();
string filename = "IEDSERVER.BIN";
Console.WriteLine("Download file " + filename);
/* Download file from server and write it to a new local file */
FileStream fs = new FileStream(filename, FileMode.Create);
BinaryWriter w = new BinaryWriter(fs);
bool fileDownloadFinished = false;
//con.GetFile (filename, new IedConnection.GetFileHandler (getFileHandler), w);
/// COMMENT SECTION WHEN USING SYNC VERSION -->
Console.WriteLine();
con.GetFileAsync(filename, delegate (UInt32 invokeId, object parameter, IedClientError err, UInt32 originalInvokeId, byte[] buffer, bool moreFollows)
{
if (err == IedClientError.IED_ERROR_OK)
{
Console.WriteLine("Received new file segment with " + buffer.Length.ToString() + " bytes, more-follows: " + moreFollows.ToString());
Console.WriteLine ("File directory tree at server:");
printFiles(con, "", "");
Console.WriteLine();
w.Write(buffer);
string filename = "IEDSERVER.BIN";
if (moreFollows == false)
fileDownloadFinished = true;
}
else
{
Console.WriteLine("File download error: " + err.ToString());
fileDownloadFinished = true;
}
Console.WriteLine("Download file " + filename);
return true;
}, w);
/* Download file from server and write it to a new local file */
FileStream fs = new FileStream(filename, FileMode.Create);
BinaryWriter w = new BinaryWriter(fs);
while (fileDownloadFinished == false)
{
Thread.Sleep(500);
}
con.GetFile(filename, new IedConnection.GetFileHandler(getFileHandler), w);
/// <-- COMMENT SECTION WHEN USING SYNC VERSION
fs.Close();
fs.Close();
con.Abort();
}
catch (IedConnectionException e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.Message);
}
// release all resources - do NOT use the object after this call!!
con.Dispose ();
}
}
// release all resources - do NOT use the object after this call!!
con.Dispose();
}
}
}

@ -4,6 +4,9 @@ using IEC61850.GOOSE.Subscriber;
using System.Threading;
using IEC61850.Common;
/// <summary>
/// This example is intended to be
/// </summary>
namespace goose_subscriber
{
class MainClass
@ -11,9 +14,10 @@ namespace goose_subscriber
private static void gooseListener (GooseSubscriber subscriber, object parameter)
{
Console.WriteLine ("Received GOOSE message:\n-------------------------");
Console.WriteLine (" GoID: " + subscriber.GetGoId());
Console.WriteLine (" GoCbRef: " + subscriber.GetGoCbRef());
Console.WriteLine (" DatSet: " + subscriber.GetDataSet());
Console.WriteLine (" stNum: " + subscriber.GetStNum ());
Console.WriteLine (" sqNum: " + subscriber.GetSqNum ());
@ -33,17 +37,27 @@ namespace goose_subscriber
GooseReceiver receiver = new GooseReceiver ();
receiver.SetInterfaceId ("eth0");
//receiver.SetInterfaceId("0"); // on windows use the interface index starting with 0
GooseSubscriber subscriber = new GooseSubscriber ("simpleIOGenericIO/LLN0$GO$gcbAnalogValues");
subscriber.SetAppId(1000);
// APP-ID has to match the APP-ID of the publisher
subscriber.SetAppId(4096);
subscriber.SetListener (gooseListener, null);
receiver.AddSubscriber (subscriber);
GooseSubscriber subscriber2 = new GooseSubscriber("simpleIOGenericIO/LLN0$GO$gcbEvents");
subscriber2.SetAppId(4096);
subscriber2.SetListener(gooseListener, null);
receiver.AddSubscriber(subscriber2);
receiver.Start ();
subscriber = null;
if (receiver.IsRunning ()) {
bool running = true;

@ -7,7 +7,7 @@
<OutputType>Exe</OutputType>
<RootNamespace>log_client</RootNamespace>
<AssemblyName>log_client</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@ -41,4 +41,4 @@
<Name>IEC61850.NET</Name>
</ProjectReference>
</ItemGroup>
</Project>
</Project>

@ -1,14 +1,12 @@
using System;
using System.Collections.Generic;
using System.Threading;
using IEC61850.Client;
using IEC61850.Common;
using System.Runtime.Remoting.Metadata.W3cXsd2001;
namespace reporting
{
class ReportingExample
class ReportingExample
{
private static void reportHandler (Report report, object parameter)
@ -25,9 +23,7 @@ namespace reporting
byte[] entryId = report.GetEntryId ();
if (entryId != null) {
SoapHexBinary shb = new SoapHexBinary(entryId);
Console.WriteLine (" entryID: " + shb.ToString ());
Console.WriteLine (" entryID: " + BitConverter.ToString(entryId));
}
if (report.HasDataSetName ()) {
@ -108,12 +104,16 @@ namespace reporting
rcb2.SetRCBValues();
rcb2.GetRCBValues();
Console.WriteLine("RCB: " + rcbReference2 + " Owner: " + BitConverter.ToString(rcb2.GetOwner()));
rcb3.GetRCBValues();
if (rcb3.IsBuffered())
Console.WriteLine ("RCB: " + rcbReference3 + " is buffered");
rcb3.InstallReportHandler(reportHandler, rcb2);
rcb3.InstallReportHandler(reportHandler, rcb3);
rcb3.SetOptFlds(ReportOptions.REASON_FOR_INCLUSION | ReportOptions.SEQ_NUM | ReportOptions.TIME_STAMP |
ReportOptions.CONF_REV | ReportOptions.ENTRY_ID | ReportOptions.DATA_REFERENCE | ReportOptions.DATA_SET);

@ -5,63 +5,128 @@ using System.Threading;
namespace server1
{
class MainClass
{
public static void Main (string[] args)
{
bool running = true;
class MainClass
{
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;
};
/* run until Ctrl-C is pressed */
Console.CancelKeyPress += delegate (object sender, ConsoleCancelEventArgs e)
{
e.Cancel = true;
running = false;
};
IedModel iedModel = ConfigFileParser.CreateModelFromConfigFile ("../../model.cfg");
IedModel iedModel = ConfigFileParser.CreateModelFromConfigFile("model.cfg");
if (iedModel == null) {
Console.WriteLine ("No valid data model found!");
return;
}
if (iedModel == null)
{
Console.WriteLine("No valid data model found!");
return;
}
DataObject spcso1 = (DataObject)iedModel.GetModelNodeByShortObjectReference ("GenericIO/GGIO1.SPCSO1");
iedModel.SetIedName("TestIED");
IedServer iedServer = new IedServer (iedModel);
DataObject spcso1 = (DataObject)iedModel.GetModelNodeByShortObjectReference("GenericIO/GGIO1.SPCSO1");
iedServer.SetControlHandler (spcso1, delegate(DataObject controlObject, object parameter, MmsValue ctlVal, bool test) {
IedServerConfig config = new IedServerConfig();
config.ReportBufferSize = 100000;
IedServer iedServer = new IedServer(iedModel, config);
iedServer.SetCheckHandler(spcso1, delegate (ControlAction action, object parameter, MmsValue ctlVal, bool test, bool interlockCheck)
{
Console.WriteLine("Received binary control command:");
Console.WriteLine(" ctlNum: " + action.GetCtlNum());
Console.WriteLine(" execution-time: " + action.GetControlTimeAsDataTimeOffset().ToString());
return CheckHandlerResult.ACCEPTED;
}, null);
iedServer.SetControlHandler(spcso1, delegate (ControlAction action, object parameter, MmsValue ctlVal, bool test)
{
bool val = ctlVal.GetBoolean();
if (val)
Console.WriteLine("received binary control command: on");
Console.WriteLine("execute binary control command: on");
else
Console.WriteLine("received binary control command: off");
Console.WriteLine("execute binary control command: off");
return ControlHandlerResult.OK;
}, null);
}, null);
DataObject spcso2 = (DataObject)iedModel.GetModelNodeByShortObjectReference("GenericIO/GGIO1.SPCSO2");
iedServer.SetSelectStateChangedHandler(spcso2, delegate (ControlAction action, object parameter, bool isSelected, SelectStateChangedReason reason)
{
DataObject cObj = action.GetControlObject();
Console.WriteLine("Control object " + cObj.GetObjectReference() + (isSelected ? " selected" : " unselected") + " reason: " + reason.ToString());
}, null);
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.ENABLED)
{
Console.WriteLine(" RptID: " + rcb.RptID);
Console.WriteLine(" DatSet: " + rcb.DataSet);
Console.WriteLine(" TrgOps: " + rcb.TrgOps.ToString());
}
if ((eventType == RCBEventType.SET_PARAMETER) || (eventType == RCBEventType.GET_PARAMETER))
{
Console.WriteLine(" param: " + parameterName);
Console.WriteLine(" result: " + serviceError.ToString());
}
}, null);
iedServer.Start(102);
iedServer.Start (102);
Console.WriteLine ("Server started");
if (iedServer.IsRunning())
{
Console.WriteLine("Server started");
GC.Collect ();
GC.Collect();
DataObject ggio1AnIn1 = (DataObject)iedModel.GetModelNodeByShortObjectReference ("GenericIO/GGIO1.AnIn1");
DataObject ggio1AnIn1 = (DataObject)iedModel.GetModelNodeByShortObjectReference("GenericIO/GGIO1.AnIn1");
DataAttribute ggio1AnIn1magF = (DataAttribute)ggio1AnIn1.GetChild ("mag.f");
DataAttribute ggio1AnIn1T = (DataAttribute)ggio1AnIn1.GetChild ("t");
DataAttribute ggio1AnIn1magF = (DataAttribute)ggio1AnIn1.GetChild("mag.f");
DataAttribute ggio1AnIn1T = (DataAttribute)ggio1AnIn1.GetChild("t");
float floatVal = 1.0f;
float floatVal = 1.0f;
while (running) {
floatVal += 1f;
iedServer.UpdateTimestampAttributeValue (ggio1AnIn1T, new Timestamp (DateTime.Now));
iedServer.UpdateFloatAttributeValue (ggio1AnIn1magF, floatVal);
Thread.Sleep (100);
}
while (running)
{
floatVal += 1f;
iedServer.UpdateTimestampAttributeValue(ggio1AnIn1T, new Timestamp(DateTime.Now));
iedServer.UpdateFloatAttributeValue(ggio1AnIn1magF, floatVal);
Thread.Sleep(100);
}
iedServer.Stop ();
Console.WriteLine ("Server stopped");
iedServer.Stop();
Console.WriteLine("Server stopped");
}
else
{
Console.WriteLine("Failed to start server");
}
iedServer.Destroy ();
}
}
iedServer.Destroy();
}
}
}

@ -2,13 +2,12 @@ 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(stVal 0 3 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
}
@ -24,30 +23,22 @@ DA(d 0 20 5 0 0);
DA(configRev 0 20 5 0 0);
DA(ldNs 0 20 11 0 0);
}
DS(Events){
DS(ControlEvents){
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);
}
DE(GGIO1$ST$SPCSO5$stVal);
DE(GGIO1$ST$SPCSO6$stVal);
DE(GGIO1$ST$SPCSO7$stVal);
DE(GGIO1$ST$SPCSO8$stVal);
DE(GGIO1$ST$SPCSO9$stVal);
DE(GGIO1$ST$SPCSO2$stSeld);
DE(GGIO1$OR$SPCSO2$opRcvd);
DE(GGIO1$OR$SPCSO2$opOk);
}
RC(ControlEventsRCB01 ControlEvents 0 ControlEvents 1 17 239 0 1000);
RC(ControlEventsRCB02 ControlEvents 0 ControlEvents 1 17 239 0 1000);
}
LN(LPHD1){
DO(PhyNam 0){
@ -66,13 +57,12 @@ 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(stVal 0 3 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
}
@ -94,11 +84,11 @@ 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(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 102);
DA(t 0 22 1 0 0);
}
DO(AnIn3 0){
DA(mag 0 27 1 1 0){
@ -115,8 +105,6 @@ 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){
@ -128,12 +116,13 @@ 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(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
DA(ctlModel 0 12 4 0 0)=1;
}
DO(SPCSO2 0){
DA(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(SBO 0 17 12 0 0);
DA(Oper 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(origin 0 27 12 0 0){
@ -145,12 +134,28 @@ 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);
DA(Cancel 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);
}
DO(SPCSO3 0){
DA(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
DA(stSeld 0 0 0 1 0);
DA(opRcvd 0 0 9 1 0);
DA(opOk 0 0 9 1 0);
DA(tOpOk 0 22 9 0 0);
DA(ctlModel 0 12 4 0 0)=2;
DA(sboTimeout 0 9 4 1 0)=2000;
DA(sboClass 0 12 4 0 0);
}
DO(SPCSO3 0){
DA(Oper 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(origin 0 27 12 0 0){
@ -162,12 +167,33 @@ 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);
DA(Cancel 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);
}
DO(SPCSO4 0){
DA(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
DA(ctlModel 0 12 4 0 0)=3;
}
DO(SPCSO4 0){
DA(SBOw 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(Oper 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(origin 0 27 12 0 0){
@ -179,58 +205,200 @@ 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);
DA(Cancel 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);
}
DO(Ind1 0){
DA(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
DA(ctlModel 0 12 4 0 0)=4;
}
DO(SPCSO5 0){
DA(Oper 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(operTm 0 22 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);
}
DO(Ind2 0){
DA(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
DA(ctlModel 0 12 4 0 0)=1;
DA(Cancel 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);
}
}
DO(SPCSO6 0){
DA(SBO 0 17 12 0 0);
DA(Oper 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(operTm 0 22 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(Cancel 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(operTm 0 22 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);
}
DO(Ind3 0){
DA(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
DA(ctlModel 0 12 4 0 0)=2;
}
DO(SPCSO7 0){
DA(Oper 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(operTm 0 22 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(Cancel 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(operTm 0 22 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);
}
DO(Ind4 0){
DA(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
DA(ctlModel 0 12 4 0 0)=3;
}
DO(SPCSO8 0){
DA(SBOw 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(operTm 0 22 12 0 0);
DA(origin 0 27 12 0 0){
DA(orCat 0 12 12 0 0);
DA(orIdent 0 13 12 0 0);
}
LN(PDUP1){
DO(Beh 0){
DA(stVal 0 12 0 1 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(Oper 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(operTm 0 22 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(Cancel 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(operTm 0 22 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(origin 0 27 0 0 0){
DA(orCat 0 12 0 0 0);
DA(orIdent 0 13 0 0 0);
}
DA(ctlNum 0 6 0 0 0);
DA(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
DA(ctlModel 0 12 4 0 0)=4;
}
DO(Mod 0){
DA(stVal 0 12 0 1 0);
DO(SPCSO9 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(Cancel 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(stVal 0 0 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;
DA(ctlModel 0 12 4 0 0)=3;
}
DO(Str 0){
DA(general 0 0 0 1 0);
DA(dirGeneral 0 12 0 1 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(Op 0){
DA(general 0 0 0 1 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(OpDlTmms 0){
DA(setVal 0 3 2 1 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(RsDlTmms 0){
DA(setVal 0 3 2 1 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);
}
}
}

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@ -7,7 +7,8 @@
<OutputType>Exe</OutputType>
<RootNamespace>server1</RootNamespace>
<AssemblyName>server1</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@ -18,6 +19,7 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>full</DebugType>
@ -41,4 +43,9 @@
<Name>IEC61850.NET</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="model.cfg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

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

@ -0,0 +1,36 @@
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("")]
// 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("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")]

@ -0,0 +1,129 @@
using System;
using IEC61850.Server;
using IEC61850.Common;
using System.Threading;
namespace server_goose_publisher
{
/// <summary>
/// This example shows how to use the server integrated GOOSE publisher from .NET
/// </summary>
/// <remarks>
/// This example requires that the native library (libiec61850) is compiled with GOOSE support.
/// </remarks>
class ServerExampleWithGoosePublisher
{
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;
};
IedModel iedModel = ConfigFileParser.CreateModelFromConfigFile("simpleIO_direct_control_goose.cfg");
if (iedModel == null)
{
Console.WriteLine("No valid data model found!");
return;
}
iedModel.SetIedName("TestIED");
DataObject spcso1 = (DataObject)iedModel.GetModelNodeByShortObjectReference("GenericIO/GGIO1.SPCSO1");
IedServerConfig config = new IedServerConfig();
config.ReportBufferSize = 100000;
IedServer iedServer = new IedServer(iedModel, config);
// Set GOOSE interface (e.g. "eth0" for Linux or "0" for Windows (first interface)
iedServer.SetGooseInterfaceId("0");
// The GoCBEventHandler can be used to track GoCB events
iedServer.SetGoCBHandler(delegate (MmsGooseControlBlock goCB, int cbEvent, object parameter)
{
if (cbEvent == 1)
{
Console.WriteLine("GCB " + goCB.LN.GetObjectReference() + ":" + goCB.Name + " enabled");
}
else
{
Console.WriteLine("GCB " + goCB.LN.GetObjectReference() + ":" + goCB.Name + " disabled");
}
}, null);
iedServer.SetCheckHandler(spcso1, delegate (ControlAction action, object parameter, MmsValue ctlVal, bool test, bool interlockCheck)
{
Console.WriteLine("Received binary control command:");
Console.WriteLine(" ctlNum: " + action.GetCtlNum());
Console.WriteLine(" execution-time: " + action.GetControlTimeAsDataTimeOffset().ToString());
return CheckHandlerResult.ACCEPTED;
}, null);
iedServer.SetControlHandler(spcso1, delegate (ControlAction action, object parameter, MmsValue ctlVal, bool test)
{
bool val = ctlVal.GetBoolean();
if (val)
Console.WriteLine("execute binary control command: on");
else
Console.WriteLine("execute binary control command: off");
return ControlHandlerResult.OK;
}, null);
DataObject spcso2 = (DataObject)iedModel.GetModelNodeByShortObjectReference("GenericIO/GGIO1.SPCSO2");
iedServer.SetSelectStateChangedHandler(spcso2, delegate (ControlAction action, object parameter, bool isSelected, SelectStateChangedReason reason)
{
DataObject cObj = action.GetControlObject();
Console.WriteLine("Control object " + cObj.GetObjectReference() + (isSelected ? " selected" : " unselected") + " reason: " + reason.ToString());
}, null);
iedServer.Start(102);
// Enable GOOSE publishing for all GOOSE control blocks
iedServer.EnableGoosePublishing();
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,63 @@
<?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')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{C14BB883-86B8-401C-B3D6-B655F55F3298}</ProjectGuid>
<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>
</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">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj">
<Project>{c35d624e-5506-4560-8074-1728f1fa1a4d}</Project>
<Name>IEC61850.NET</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

@ -0,0 +1,217 @@
MODEL(simpleIO){
LD(GenericIO){
LN(LLN0){
DO(Mod 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 3 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(Events2){
DE(GGIO1$ST$SPCSO1);
DE(GGIO1$ST$SPCSO2);
DE(GGIO1$ST$SPCSO3);
DE(GGIO1$ST$SPCSO4);
}
DS(Events3){
DE(GGIO1$ST$SPCSO1$stVal);
DE(GGIO1$ST$SPCSO1$q);
DE(GGIO1$ST$SPCSO2$stVal);
DE(GGIO1$ST$SPCSO2$q);
DE(GGIO1$ST$SPCSO3$stVal);
DE(GGIO1$ST$SPCSO3$q);
DE(GGIO1$ST$SPCSO4$stVal);
DE(GGIO1$ST$SPCSO4$q);
}
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 175 50 1000);
RC(AnalogValuesRCB01 AnalogValues 0 AnalogValues 1 24 175 50 1000);
GC(gcbEvents events Events3 2 0 1000 3000 ){
PA(4 1 4096 010ccd010001);
}
GC(gcbAnalogValues analog AnalogValues 2 0 -1 -1 ){
PA(4 1 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(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 3 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 0){
DA(f 0 10 1 1 0);
}
DA(q 0 23 1 2 0);
DA(t 0 22 1 0 0);
}
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);
}
}
}
}

@ -1,261 +1,275 @@
<?xml version="1.0" encoding="UTF-8"?>
<SCL xmlns="http://www.iec.ch/61850/2003/SCL">
<Header id="" nameStructure="IEDName">
</Header>
<Communication>
<SubNetwork name="subnetwork1" type="8-MMS">
<Text>Station bus</Text>
<BitRate unit="b/s">10</BitRate>
<ConnectedAP iedName="simpleIO" apName="accessPoint1">
<Address>
<P type="IP">10.0.0.2</P>
<P type="IP-SUBNET">255.255.255.0</P>
<P type="IP-GATEWAY">10.0.0.1</P>
<P type="OSI-TSEL">0001</P>
<P type="OSI-PSEL">00000001</P>
<P type="OSI-SSEL">0001</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>
</GSE>
<GSE ldInst="GenericIO" cbName="gcbAnalogValues">
<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>
</GSE>
</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">
<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="AnalogValues" desc="analog values">
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="MX" lnInst="1" doName="AnIn1" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="MX" lnInst="1" doName="AnIn2" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="MX" lnInst="1" doName="AnIn3" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="MX" lnInst="1" doName="AnIn4" />
</DataSet>
<ReportControl name="EventsRCB" confRev="1" datSet="Events" rptID="Events" buffered="false" intgPd="1000" bufTime="50">
<TrgOps period="true" />
<OptFields seqNum="true" timeStamp="true" dataSet="true" reasonCode="true" entryID="true" configRef="true" />
<RptEnabled max="1" />
</ReportControl>
<ReportControl name="AnalogValuesRCB" confRev="1" datSet="AnalogValues" rptID="AnalogValues" buffered="false" intgPd="1000" bufTime="50">
<TrgOps period="true" />
<OptFields seqNum="true" timeStamp="true" dataSet="true" reasonCode="true" entryID="true" configRef="true" />
<RptEnabled max="1" />
</ReportControl>
<GSEControl appID="events" name="gcbEvents" type="GOOSE" datSet="Events" confRev="2" minTime="1000" maxTime="3000" />
<GSEControl appID="analog" name="gcbAnalogValues" type="GOOSE" datSet="AnalogValues" confRev="2"/>
<DOI name="Mod">
<DAI name="ctlModel">
<Val>status-only</Val>
</DAI>
</DOI>
</LN0>
<LN lnClass="LPHD" lnType="LPHD1" inst="1" prefix="" />
<LN lnClass="GGIO" lnType="GGIO1" inst="1" prefix="">
<DOI name="Mod">
<DAI name="ctlModel">
<Val>status-only</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>
</LDevice>
</Server>
</AccessPoint>
</IED>
<DataTypeTemplates>
<LNodeType id="LLN01" lnClass="LLN0">
<DO name="Mod" type="INC_1_Mod" />
<DO name="Beh" type="INS_1_Beh" />
<DO name="Health" type="INS_1_Beh" />
<DO name="NamPlt" type="LPL_1_NamPlt" />
</LNodeType>
<LNodeType id="LPHD1" lnClass="LPHD">
<DO name="PhyNam" type="DPL_1_PhyNam" />
<DO name="PhyHealth" type="INS_1_Beh" />
<DO name="Proxy" type="SPS_1_Proxy" />
</LNodeType>
<LNodeType id="GGIO1" lnClass="GGIO">
<DO name="Mod" type="INC_2_Mod" />
<DO name="Beh" type="INS_1_Beh" />
<DO name="Health" type="INS_1_Beh" />
<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_2_SPCSO1" />
<DO name="SPCSO2" type="SPC_1_SPCSO2" />
<DO name="SPCSO3" type="SPC_1_SPCSO3" />
<DO name="SPCSO4" type="SPC_1_SPCSO1" />
<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>
<DOType id="INC_1_Mod" cdc="INC">
<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="INS_1_Beh" cdc="INS">
<DA name="stVal" bType="INT32" 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="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>
<DOType id="INC_2_Mod" cdc="INC">
<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="SPC_2_SPCSO1" 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>
<DOType id="SPC_1_SPCSO2" 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>
<DOType id="SPC_1_SPCSO3" 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="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>
</DataTypeTemplates>
</SCL>
<?xml version="1.0" encoding="UTF-8"?>
<SCL xmlns="http://www.iec.ch/61850/2003/SCL">
<Header id="" nameStructure="IEDName">
</Header>
<Communication>
<SubNetwork name="subnetwork1" type="8-MMS">
<ConnectedAP iedName="simpleIO" apName="accessPoint1">
<Address>
<P type="IP">10.0.0.2</P>
<P type="IP-SUBNET">255.255.255.0</P>
<P type="IP-GATEWAY">10.0.0.1</P>
<P type="OSI-TSEL">0001</P>
<P type="OSI-PSEL">00000001</P>
<P type="OSI-SSEL">0001</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>
<GSE ldInst="GenericIO" cbName="gcbAnalogValues">
<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>
</GSE>
</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">
<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="Events3" desc="Events3">
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO1" daName="stVal" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO1" daName="q" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO2" daName="stVal" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO2" daName="q" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO3" daName="stVal" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO3" daName="q" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO4" daName="stVal" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO4" daName="q" />
</DataSet>
<DataSet name="AnalogValues" desc="analog values">
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="MX" lnInst="1" doName="AnIn1" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="MX" lnInst="1" doName="AnIn2" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="MX" lnInst="1" doName="AnIn3" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="MX" lnInst="1" doName="AnIn4" />
</DataSet>
<ReportControl name="EventsRCB" confRev="1" datSet="Events" rptID="Events" 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="AnalogValuesRCB" confRev="1" datSet="AnalogValues" rptID="AnalogValues" buffered="false" intgPd="1000" bufTime="50">
<TrgOps period="true" />
<OptFields seqNum="true" timeStamp="true" dataSet="true" reasonCode="true" configRef="true" />
<RptEnabled max="1" />
</ReportControl>
<GSEControl appID="events" name="gcbEvents" type="GOOSE" datSet="Events3" confRev="2" />
<GSEControl appID="analog" name="gcbAnalogValues" type="GOOSE" datSet="AnalogValues" confRev="2"/>
<DOI name="Mod">
<DAI name="ctlModel">
<Val>status-only</Val>
</DAI>
</DOI>
</LN0>
<LN lnClass="LPHD" lnType="LPHD1" inst="1" prefix="" />
<LN lnClass="GGIO" lnType="GGIO1" inst="1" prefix="">
<DOI name="Mod">
<DAI name="ctlModel">
<Val>status-only</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>
</LDevice>
</Server>
</AccessPoint>
</IED>
<DataTypeTemplates>
<LNodeType id="LLN01" lnClass="LLN0">
<DO name="Mod" type="INC_1_Mod" />
<DO name="Beh" type="INS_1_Beh" />
<DO name="Health" type="INS_1_Beh" />
<DO name="NamPlt" type="LPL_1_NamPlt" />
</LNodeType>
<LNodeType id="LPHD1" lnClass="LPHD">
<DO name="PhyNam" type="DPL_1_PhyNam" />
<DO name="PhyHealth" type="INS_1_Beh" />
<DO name="Proxy" type="SPS_1_Proxy" />
</LNodeType>
<LNodeType id="GGIO1" lnClass="GGIO">
<DO name="Mod" type="INC_2_Mod" />
<DO name="Beh" type="INS_1_Beh" />
<DO name="Health" type="INS_1_Beh" />
<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_2_SPCSO1" />
<DO name="SPCSO2" type="SPC_1_SPCSO2" />
<DO name="SPCSO3" type="SPC_1_SPCSO3" />
<DO name="SPCSO4" type="SPC_1_SPCSO1" />
<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>
<DOType id="INC_1_Mod" cdc="INC">
<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="INS_1_Beh" cdc="INS">
<DA name="stVal" bType="INT32" 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="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>
<DOType id="INC_2_Mod" cdc="INC">
<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="SPC_2_SPCSO1" 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>
<DOType id="SPC_1_SPCSO2" 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>
<DOType id="SPC_1_SPCSO3" 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="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>
</DataTypeTemplates>
</SCL>

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@ -7,7 +7,8 @@
<OutputType>Exe</OutputType>
<RootNamespace>sv_subscriber</RootNamespace>
<AssemblyName>sv_subscriber</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@ -41,4 +42,4 @@
<Name>IEC61850.NET</Name>
</ProjectReference>
</ItemGroup>
</Project>
</Project>

@ -49,6 +49,15 @@ namespace tests
Assert.AreEqual(7, val.BitStringToUInt32());
}
[Test ()]
public void MmsValueUtcTime ()
{
var val = MmsValue.NewUtcTime (100000);
val.GetUtcTimeInMs ();
Assert.AreEqual (val.GetUtcTimeInMs (), 100000);
}
[Test()]
public void MmsValueOctetString ()
{
@ -105,6 +114,57 @@ namespace tests
Assert.AreEqual (val.ToFloat (), (float)0.1234);
}
[Test()]
public void MmsValueArray()
{
MmsValue val = MmsValue.NewEmptyArray (3);
val.SetElement (0, new MmsValue (1));
val.SetElement (1, new MmsValue (2));
val.SetElement (2, new MmsValue (3));
Assert.AreEqual (val.GetType (), MmsType.MMS_ARRAY);
Assert.AreEqual (val.Size (), 3);
MmsValue elem0 = val.GetElement (0);
Assert.AreEqual (elem0.GetType (), MmsType.MMS_INTEGER);
Assert.AreEqual (elem0.ToInt32 (), 1);
MmsValue elem2 = val.GetElement (2);
Assert.AreEqual (elem2.GetType (), MmsType.MMS_INTEGER);
Assert.AreEqual (elem2.ToInt32 (), 3);
val.SetElement (0, null);
val.SetElement (1, null);
val.SetElement (2, null);
}
[Test()]
public void MmsValueStructure()
{
MmsValue val = MmsValue.NewEmptyStructure (2);
val.SetElement (0, new MmsValue(true));
val.SetElement (1, MmsValue.NewBitString (10));
Assert.AreEqual (val.GetType (), MmsType.MMS_STRUCTURE);
Assert.AreEqual (val.Size (), 2);
MmsValue elem0 = val.GetElement (0);
Assert.AreEqual (elem0.GetType (), MmsType.MMS_BOOLEAN);
Assert.AreEqual (elem0.GetBoolean(), true);
MmsValue elem1 = val.GetElement (1);
Assert.AreEqual (elem1.GetType (), MmsType.MMS_BIT_STRING);
val.SetElement (0, null);
val.SetElement (1, null);
}
[Test ()]
public void Timestamps()
{
@ -184,7 +244,9 @@ namespace tests
Assert.AreEqual (list.ToArray () [0], "simpleIOGenericIO");
iedServer.Stop ();
Assert.IsTrue(iedServer.IsRunning());
iedServer.Stop ();
iedServer.Destroy ();
}
@ -229,10 +291,38 @@ namespace tests
Assert.IsNotNull (modelNode);
}
[Test ()]
[Test()]
public void AccessDataModelServerSideNavigateModelNode()
{
IedModel iedModel = ConfigFileParser.CreateModelFromConfigFile("../../model.cfg");
ModelNode modelNode = iedModel.GetModelNodeByShortObjectReference("GenericIO/GGIO1.AnIn1");
Assert.IsNotNull(modelNode);
Assert.IsTrue(modelNode.GetType().Equals(typeof(DataObject)));
var children = modelNode.GetChildren();
Assert.AreEqual(3, children.Count);
ModelNode mag = children.First.Value;
Assert.AreEqual("mag", mag.GetName());
ModelNode t = children.Last.Value;
Assert.AreEqual("t", t.GetName());
//modelNode = iedModel.GetModelNodeByShortObjectReference("GenericIO/GGIO1.AnIn1.mag.f");
//Assert.IsTrue(modelNode.GetType().Equals(typeof(IEC61850.Server.DataAttribute)));
}
[Test ()]
public void AccessDataModelClientServer()
{
IedModel iedModel = ConfigFileParser.CreateModelFromConfigFile ("../../model.cfg");
IedModel iedModel = ConfigFileParser.CreateModelFromConfigFile("../../model.cfg");
ModelNode ind1 = iedModel.GetModelNodeByShortObjectReference ("GenericIO/GGIO1.Ind1.stVal");
@ -322,10 +412,62 @@ namespace tests
iedServer.Destroy ();
}
[Test()]
[Test()]
public void ControlWriteAccessComplexDAToServer()
{
IedModel iedModel = ConfigFileParser.CreateModelFromConfigFile("../../model2.cfg");
IEC61850.Server.DataAttribute setAnVal_setMag = (IEC61850.Server.DataAttribute)iedModel.GetModelNodeByShortObjectReference("GenericIO/LLN0.SetAnVal.setMag");
IedServer iedServer = new IedServer(iedModel);
int handlerCalled = 0;
MmsValue receivedValue = null;
iedServer.SetWriteAccessPolicy(FunctionalConstraint.SP, AccessPolicy.ACCESS_POLICY_DENY);
iedServer.HandleWriteAccessForComplexAttribute(setAnVal_setMag, delegate (IEC61850.Server.DataAttribute dataAttr, MmsValue value, ClientConnection con, object parameter) {
receivedValue = value;
handlerCalled++;
return MmsDataAccessError.SUCCESS;
}, null);
iedServer.Start(10002);
IedConnection connection = new IedConnection();
connection.Connect("localhost", 10002);
MmsValue complexValue = MmsValue.NewEmptyStructure(1);
complexValue.SetElement(0, new MmsValue((float)1.0));
connection.WriteValue("simpleIOGenericIO/LLN0.SetAnVal.setMag", FunctionalConstraint.SP, complexValue);
Assert.NotNull(receivedValue);
Assert.AreEqual(MmsType.MMS_STRUCTURE, receivedValue.GetType());
Assert.AreEqual(1.0, receivedValue.GetElement(0).ToFloat());
receivedValue.Dispose();
receivedValue = null;
connection.WriteValue("simpleIOGenericIO/LLN0.SetAnVal.setMag.f", FunctionalConstraint.SP, new MmsValue((float)2.0));
Assert.NotNull(receivedValue);
Assert.AreEqual(MmsType.MMS_FLOAT, receivedValue.GetType());
Assert.AreEqual(2.0, receivedValue.ToFloat());
connection.Abort();
iedServer.Stop();
iedServer.Dispose();
}
[Test()]
public void WriteAccessPolicy()
{
IedModel iedModel = ConfigFileParser.CreateModelFromConfigFile ("../../model.cfg");
IEC61850.Server.DataAttribute opDlTmms = (IEC61850.Server.DataAttribute) iedModel.GetModelNodeByShortObjectReference("GenericIO/PDUP1.OpDlTmms.setVal");
@ -333,7 +475,7 @@ namespace tests
IedServer iedServer = new IedServer (iedModel);
iedServer.HandleWriteAccess (opDlTmms, delegate(IEC61850.Server.DataAttribute dataAttr, MmsValue value, ClientConnection con, object parameter) {
iedServer.HandleWriteAccess (opDlTmms, delegate(IEC61850.Server.DataAttribute dataAttr, MmsValue value, ClientConnection con, object parameter) {
return MmsDataAccessError.SUCCESS;
}, null);
@ -344,7 +486,9 @@ namespace tests
connection.Connect ("localhost", 10002);
connection.WriteValue ("simpleIOGenericIO/PDUP1.RsDlTmms.setVal", FunctionalConstraint.SP, new MmsValue ((int)1234));
iedServer.SetWriteAccessPolicy(FunctionalConstraint.SP, AccessPolicy.ACCESS_POLICY_ALLOW);
connection.WriteValue ("simpleIOGenericIO/PDUP1.RsDlTmms.setVal", FunctionalConstraint.SP, new MmsValue ((int)1234));
iedServer.SetWriteAccessPolicy (FunctionalConstraint.SP, AccessPolicy.ACCESS_POLICY_DENY);
@ -365,7 +509,7 @@ namespace tests
iedServer.Stop ();
iedServer.Destroy ();
iedServer.Dispose();
}
[Test()]
@ -381,7 +525,17 @@ namespace tests
IedServer iedServer = new IedServer (iedModel);
iedServer.SetControlHandler (spcso1, delegate(DataObject controlObject, object parameter, MmsValue ctlVal, bool test) {
iedServer.SetControlHandler (spcso1, delegate(ControlAction action, object parameter, MmsValue ctlVal, bool test) {
byte [] orIdent = action.GetOrIdent ();
string orIdentStr = System.Text.Encoding.UTF8.GetString (orIdent, 0, orIdent.Length);
Assert.AreEqual ("TEST1234", orIdentStr);
Assert.AreEqual (OrCat.MAINTENANCE, action.GetOrCat ());
Assert.AreSame (spcso1, action.GetControlObject ());
handlerCalled++;
return ControlHandlerResult.OK;
}, null);
@ -393,6 +547,7 @@ namespace tests
connection.Connect ("localhost", 10002);
ControlObject controlClient = connection.CreateControlObject ("simpleIOGenericIO/GGIO1.SPCSO1");
controlClient.SetOrigin ("TEST1234", OrCat.MAINTENANCE);
Assert.IsNotNull (controlClient);
@ -404,7 +559,7 @@ namespace tests
iedServer.Stop ();
iedServer.Destroy ();
iedServer.Dispose();
}
@ -453,6 +608,8 @@ namespace tests
Assert.AreEqual ("127.0.0.1:", ipAddress.Substring (0, 10));
iedServer.Stop ();
iedServer.Dispose();
}
[Test()]
@ -481,6 +638,45 @@ namespace tests
Assert.AreEqual (Validity.QUESTIONABLE, q.Validity);
}
}
[Test()]
public void MmsValueCreateStructureAndAddElement()
{
MmsValue structure1 = MmsValue.NewEmptyStructure(1);
MmsValue structure2 = MmsValue.NewEmptyStructure(1);
MmsValue element = MmsValue.NewEmptyStructure(1);
structure1.SetElement(0, element);
/* Clone is required when adding the value to another structure or element */
MmsValue elementClone = element.Clone();
structure2.SetElement(0, elementClone);
element.Dispose();
structure1.Dispose();
structure2.Dispose();
Assert.AreEqual(true, true);
}
[Test()]
public void MmsValueClone()
{
MmsValue boolValue = new MmsValue(true);
MmsValue boolClone = boolValue.Clone();
boolValue.Dispose();
boolClone.Dispose();
MmsValue structure = MmsValue.NewEmptyStructure(1);
MmsValue structureClone = structure.Clone();
structure.Dispose();
structureClone.Dispose();
}
}
}

@ -0,0 +1,446 @@
MODEL(simpleIO){
LD(GenericIO){
LN(LLN0){
DO(Mod 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 3 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);
}
DO(SetInt1 0){
DA(setVal 0 3 2 1 0);
}
DO(SetInt2 0){
DA(setVal 0 3 2 1 0);
}
DO(SetInt3 0){
DA(setVal 0 3 2 1 0);
}
DO(SetInt4 0){
DA(setVal 0 3 2 1 0);
}
DO(SetBool1 0){
DA(setVal 0 0 2 1 0);
}
DO(SetBool2 0){
DA(setVal 0 0 2 1 0);
}
DO(SetBool3 0){
DA(setVal 0 0 2 1 0);
}
DO(SetBool4 0){
DA(setVal 0 0 2 1 0);
}
DO(Int64 0){
DA(stVal 0 4 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
}
DO(SetAnVal 0){
DA(setMag 0 27 2 1 0){
DA(f 0 10 2 1 0);
}
}
DS(Events){
DE(GGIO1$ST$SPCSO1$stVal);
DE(GGIO1$ST$SPCSO2$stVal);
DE(GGIO1$ST$SPCSO3$stVal);
DE(GGIO1$ST$SPCSO4$stVal);
}
DS(EventsFCDO){
DE(GGIO1$ST$SPCSO1);
DE(GGIO1$ST$SPCSO2);
DE(GGIO1$ST$SPCSO3);
DE(GGIO1$ST$SPCSO4);
}
DS(Booleans){
DE(LLN0$SP$SetBool1$setVal);
DE(LLN0$SP$SetBool2$setVal);
DE(LLN0$SP$SetBool3$setVal);
DE(LLN0$SP$SetBool4$setVal);
}
DS(Integers){
DE(LLN01$SP$SetInt1$setVal);
DE(LLN01$SP$SetInt2$setVal);
DE(LLN01$SP$SetInt3$setVal);
DE(LLN01$SP$SetInt4$setVal);
}
RC(EventsRCB01 Events1 0 Events 1 24 239 50 1000);
RC(EventsRCB02 Events1 0 Events 1 24 239 50 1000);
RC(BufferedRCB01 Events1 1 Events 1 24 239 50 1000);
RC(BufferedRCB02 Events1 1 Events 1 24 239 50 1000);
GC(gcbEvents events Events 1 0 1000 3000 ){
PA(4 1 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(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 3 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(dU 0 21 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 0){
DA(f 0 10 1 1 0);
}
DA(q 0 23 1 2 0);
DA(t 0 22 1 0 0);
}
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(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(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
DA(ctlModel 0 12 4 0 0)=1;
}
DO(SPCSO2 0){
DA(SBO 0 17 12 0 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(Cancel 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(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
DA(ctlModel 0 12 4 0 0)=2;
DA(sboClass 0 12 4 0 0);
}
DO(SPCSO3 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(Cancel 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(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
DA(ctlModel 0 12 4 0 0)=3;
}
DO(SPCSO4 0){
DA(SBOw 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(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(Cancel 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(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
DA(ctlModel 0 12 4 0 0)=4;
}
DO(SPCSO5 0){
DA(Oper 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(operTm 0 22 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(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
DA(ctlModel 0 12 4 0 0)=1;
DA(Cancel 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);
}
}
DO(SPCSO6 0){
DA(SBO 0 17 12 0 0);
DA(Oper 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(operTm 0 22 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(Cancel 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(operTm 0 22 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(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
DA(ctlModel 0 12 4 0 0)=2;
}
DO(SPCSO7 0){
DA(Oper 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(operTm 0 22 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(Cancel 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(operTm 0 22 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(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
DA(ctlModel 0 12 4 0 0)=3;
}
DO(SPCSO8 0){
DA(SBOw 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(operTm 0 22 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(Oper 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(operTm 0 22 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(Cancel 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(operTm 0 22 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(origin 0 27 0 0 0){
DA(orCat 0 12 0 0 0);
DA(orIdent 0 13 0 0 0);
}
DA(ctlNum 0 6 0 0 0);
DA(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
DA(ctlModel 0 12 4 0 0)=4;
}
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);
}
DO(SchdAbsTm 0){
DA(val 24 10 2 1 0);
}
}
LN(MHAI1){
DO(HA 0){
DO(phsAHar 16){
DA(cVal 0 27 1 5 0){
DA(mag 0 27 1 5 0){
DA(f 0 10 1 5 0);
}
DA(ang 0 27 1 5 0){
DA(f 0 10 1 5 0);
}
}
DA(q 0 23 1 2 0);
DA(t 0 22 1 0 0);
}
DA(numHar 0 7 4 1 0)=16;
DA(numCyc 0 7 4 1 0);
DA(evalTm 0 7 4 1 0);
DA(frequency 0 10 4 1 0);
}
}
}
}

@ -15,10 +15,20 @@
<P type="OSI-PSEL">00000001</P>
<P type="OSI-SSEL">0001</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>
</ConnectedAP>
</SubNetwork>
</Communication>
<IED name="test">
<IED name="simpleIO">
<Services>
<DynAssociation />
<GetDirectory />
@ -37,9 +47,52 @@
<AccessPoint name="accessPoint1">
<Server>
<Authentication />
<LDevice inst="ComplexArray">
<LDevice inst="GenericIO">
<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="EventsFCDO" desc="EventsFCDO">
<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="Booleans" desc="Booleans">
<FCDA ldInst="GenericIO" lnClass="LLN0" fc="SP" doName="SetBool1" daName="setVal" />
<FCDA ldInst="GenericIO" lnClass="LLN0" fc="SP" doName="SetBool2" daName="setVal" />
<FCDA ldInst="GenericIO" lnClass="LLN0" fc="SP" doName="SetBool3" daName="setVal" />
<FCDA ldInst="GenericIO" lnClass="LLN0" fc="SP" doName="SetBool4" daName="setVal" />
</DataSet>
<DataSet name="Integers" desc="Integers">
<FCDA ldInst="GenericIO" lnClass="LLN0" fc="SP" lnInst="1" doName="SetInt1" daName="setVal" />
<FCDA ldInst="GenericIO" lnClass="LLN0" fc="SP" lnInst="1" doName="SetInt2" daName="setVal" />
<FCDA ldInst="GenericIO" lnClass="LLN0" fc="SP" lnInst="1" doName="SetInt3" daName="setVal" />
<FCDA ldInst="GenericIO" lnClass="LLN0" fc="SP" lnInst="1" doName="SetInt4" daName="setVal" />
</DataSet>
<ReportControl name="EventsRCB" confRev="1" datSet="Events" rptID="Events1" buffered="false" intgPd="1000" bufTime="50" indexed="true">
<TrgOps period="true" />
<OptFields seqNum="true" timeStamp="true" dataSet="true" reasonCode="true" entryID="true" configRef="true" />
<RptEnabled max="2" />
</ReportControl>
<ReportControl name="BufferedRCB" confRev="1" datSet="Events" rptID="Events1" buffered="true" intgPd="1000" bufTime="50" indexed="true">
<TrgOps period="true" />
<OptFields seqNum="true" timeStamp="true" dataSet="true" reasonCode="true" entryID="true" configRef="true" />
<RptEnabled max="2" />
</ReportControl>
<GSEControl appID="events" name="gcbEvents" type="GOOSE" datSet="Events" confRev="1"/>
<DOI name="Mod">
<DAI name="ctlModel">
<Val>status-only</Val>
@ -47,6 +100,53 @@
</DOI>
</LN0>
<LN lnClass="LPHD" lnType="LPHD1" inst="1" prefix="" />
<LN lnClass="GGIO" lnType="GGIO1" inst="1" prefix="">
<DOI name="Mod">
<DAI name="ctlModel">
<Val>status-only</Val>
</DAI>
</DOI>
<DOI name="SPCSO1">
<DAI name="ctlModel">
<Val>direct-with-normal-security</Val>
</DAI>
</DOI>
<DOI name="SPCSO2">
<DAI name="ctlModel">
<Val>sbo-with-normal-security</Val>
</DAI>
</DOI>
<DOI name="SPCSO3">
<DAI name="ctlModel">
<Val>direct-with-enhanced-security</Val>
</DAI>
</DOI>
<DOI name="SPCSO4">
<DAI name="ctlModel">
<Val>sbo-with-enhanced-security</Val>
</DAI>
</DOI>
<DOI name="SPCSO5">
<DAI name="ctlModel">
<Val>direct-with-normal-security</Val>
</DAI>
</DOI>
<DOI name="SPCSO6">
<DAI name="ctlModel">
<Val>sbo-with-normal-security</Val>
</DAI>
</DOI>
<DOI name="SPCSO7">
<DAI name="ctlModel">
<Val>direct-with-enhanced-security</Val>
</DAI>
</DOI>
<DOI name="SPCSO8">
<DAI name="ctlModel">
<Val>sbo-with-enhanced-security</Val>
</DAI>
</DOI>
</LN>
<LN lnClass="MHAI" lnType="MHAI1" inst="1" prefix="">
<DOI name="HA">
<DAI name="numHar">
@ -64,6 +164,16 @@
<DO name="Beh" type="INS_1_Beh" />
<DO name="Health" type="INS_1_Beh" />
<DO name="NamPlt" type="LPL_1_NamPlt" />
<DO name="SetInt1" type="ISP" />
<DO name="SetInt2" type="ISP" />
<DO name="SetInt3" type="ISP" />
<DO name="SetInt4" type="ISP" />
<DO name="SetBool1" type="SPG_1" />
<DO name="SetBool2" type="SPG_1" />
<DO name="SetBool3" type="SPG_1" />
<DO name="SetBool4" type="SPG_1" />
<DO name="Int64" type="INS_64" />
<DO name="SetAnVal" type="ASG" />
</LNodeType>
<LNodeType id="LPHD1" lnClass="LPHD">
<DO name="PhyNam" type="DPL_1_PhyNam" />
@ -91,12 +201,26 @@
<DO name="Ind2" type="SPS_1_Proxy" />
<DO name="Ind3" type="SPS_1_Proxy" />
<DO name="Ind4" type="SPS_1_Proxy" />
<DO name="SchdAbsTm" type="SCA_1_SchdAbsTm" />
</LNodeType>
<LNodeType id="MHAI1" lnClass="MHAI">
<DO name="HA" type="HWYE_1_HA" />
</LNodeType>
<DOType id="SPG_1" cdc="SPG">
<DA name="setVal" bType="BOOLEAN" fc="SP" dchg="true" />
</DOType>
<DOType id="ASG" cdc="ASG">
<DA name="setMag" bType="Struct" type="AnalogueValue" fc="SP" dchg="true" />
</DOType>
<DOType id="ISP" cdc="INS">
<DA name="setVal" bType="INT32" fc="SP" dchg="true" />
</DOType>
<DOType id="HWYE_1_HA" cdc="HWYE">
<SDO name="phsAHar" type="CMV_1_phsAHar" count="16" />
<DA name="numHar" bType="INT16U" fc="CF" dchg="true" />
@ -105,6 +229,11 @@
<DA name="frequency" bType="FLOAT32" fc="CF" dchg="true" />
</DOType>
<DOType id="SCA_1_SchdAbsTm" cdc="SCA">
<DA name="val" bType="FLOAT32" count="24" fc="SP" dchg="true" />
</DOType>
<DOType id="CMV_1_phsAHar" cdc="CMV">
<DA name="cVal" bType="Struct" type="Vector" fc="MX" dchg="true" dupd="true" />
<DA name="q" bType="Quality" fc="MX" qchg="true" />
@ -126,6 +255,13 @@
<DA name="q" bType="Quality" fc="ST" qchg="true" />
<DA name="t" bType="Timestamp" fc="ST" />
</DOType>
<DOType id="INS_64" cdc="INS">
<DA name="stVal" bType="INT64" 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" />
@ -169,7 +305,7 @@
<DA name="ctlModel" type="CtlModels" bType="Enum" fc="CF" />
</DOType>
<DOType id="MV_1_AnIn1" cdc="MV">
<DA name="mag" type="AnalogueValue_1" bType="Struct" fc="MX" dchg="true" />
<DA name="mag" type="" bType="Struct" fc="MX" dchg="true" />
<DA name="q" bType="Quality" fc="MX" qchg="true" />
<DA name="t" bType="Timestamp" fc="MX" />
</DOType>
@ -243,7 +379,7 @@
<BDA name="Test" bType="BOOLEAN" />
<BDA name="Check" bType="Check" />
</DAType>
<DAType id="AnalogueValue_1">
<DAType id="">
<BDA name="f" bType="FLOAT32" />
</DAType>
<DAType id="SPCCancel_1">

@ -0,0 +1,85 @@
using System;
using System.Threading;
using System.Security.Cryptography.X509Certificates;
using IEC61850.Server;
using IEC61850.Common;
using IEC61850.TLS;
namespace tls_server_example
{
class MainClass
{
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;
};
IedModel iedModel = ConfigFileParser.CreateModelFromConfigFile ("model.cfg");
if (iedModel == null) {
Console.WriteLine ("No valid data model found!");
return;
}
DataObject spcso1 = (DataObject)iedModel.GetModelNodeByShortObjectReference ("GenericIO/GGIO1.SPCSO1");
TLSConfiguration tlsConfig = new TLSConfiguration ();
tlsConfig.SetOwnCertificate (new X509Certificate2 ("server.cer"));
tlsConfig.SetOwnKey ("server-key.pem", null);
// Add a CA certificate to check the certificate provided by the server - not required when ChainValidation == false
tlsConfig.AddCACertificate (new X509Certificate2 ("root.cer"));
// Check if the certificate is signed by a provided CA
tlsConfig.ChainValidation = true;
// Check that the shown server certificate is in the list of allowed certificates
tlsConfig.AllowOnlyKnownCertificates = false;
IedServer iedServer = new IedServer (iedModel, tlsConfig);
iedServer.SetControlHandler (spcso1, delegate(ControlAction action, object parameter, MmsValue ctlVal, bool test) {
bool val = ctlVal.GetBoolean();
if (val)
Console.WriteLine("received binary control command: on");
else
Console.WriteLine("received binary control command: off");
return ControlHandlerResult.OK;
}, null);
iedServer.Start ();
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");
iedServer.Destroy ();
}
}
}

@ -0,0 +1,27 @@
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.
//[assembly: AssemblyDelaySign(false)]
//[assembly: AssemblyKeyFile("")]

@ -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);
}
}
}
}

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{B63F7A81-1D3A-4F2F-A7C2-D6F77E5BD307}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>tls_server_example</RootNamespace>
<AssemblyName>tls_server_example</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</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>
</ItemGroup>
<ItemGroup>
<None Include="server-key.pem">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="server.cer">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="root.cer">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="model.cfg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

@ -11,18 +11,25 @@ add_subdirectory(server_example_61400_25)
add_subdirectory(server_example_setting_groups)
add_subdirectory(server_example_logging)
add_subdirectory(server_example_files)
add_subdirectory(server_example_substitution)
add_subdirectory(server_example_service_tracking)
add_subdirectory(server_example_deadband)
add_subdirectory(iec61850_client_example1)
add_subdirectory(iec61850_client_example2)
add_subdirectory(iec61850_client_example3)
add_subdirectory(iec61850_client_example_control)
add_subdirectory(iec61850_client_example4)
add_subdirectory(iec61850_client_example5)
add_subdirectory(iec61850_client_example_reporting)
add_subdirectory(iec61850_client_example_log)
add_subdirectory(iec61850_client_example_array)
add_subdirectory(iec61850_client_example_files)
add_subdirectory(iec61850_client_example_async)
add_subdirectory(iec61850_client_file_async)
if(NOT WIN32)
add_subdirectory(iec61850_client_example_files)
endif()
if (NOT WIN32)
add_subdirectory(mms_utility)
endif(NOT WIN32)
if(WIN32)
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../third_party/winpcap/Lib/wpcap.lib")
@ -40,6 +47,7 @@ endif(WITH_MBEDTLS)
if(${BUILD_SV_GOOSE_EXAMPLES})
add_subdirectory(server_example_goose)
add_subdirectory(goose_observer)
add_subdirectory(goose_subscriber)
add_subdirectory(goose_publisher)
add_subdirectory(sv_subscriber)

@ -1,11 +1,11 @@
EXAMPLE_DIRS = iec61850_client_example1
EXAMPLE_DIRS += iec61850_client_example2
EXAMPLE_DIRS += iec61850_client_example3
EXAMPLE_DIRS += iec61850_client_example4
EXAMPLE_DIRS += iec61850_client_example5
EXAMPLE_DIRS += iec61850_client_example_reporting
EXAMPLE_DIRS += iec61850_client_example_log
EXAMPLE_DIRS += iec61850_client_example_array
EXAMPLE_DIRS += iec61850_client_example_control
EXAMPLE_DIRS += server_example_simple
EXAMPLE_DIRS += server_example_basic_io
EXAMPLE_DIRS += server_example_password_auth
@ -18,8 +18,9 @@ EXAMPLE_DIRS += server_example_complex_array
EXAMPLE_DIRS += server_example_61400_25
EXAMPLE_DIRS += server_example_threadless
EXAMPLE_DIRS += server_example_setting_groups
EXAMPLE_DIRS += server_example_logging
EXAMPLE_DIRS += server_example_files
EXAMPLE_DIRS += server_example_substitution
EXAMPLE_DIRS += server_example_deadband
EXAMPLE_DIRS += goose_subscriber
EXAMPLE_DIRS += goose_publisher
EXAMPLE_DIRS += sv_subscriber

@ -0,0 +1,21 @@
set(goose_observer_SRCS
goose_observer.c
)
IF(MSVC)
set_source_files_properties(${goose_observer_SRCS}
PROPERTIES LANGUAGE CXX)
ENDIF(MSVC)
add_executable(goose_observer
${goose_observer_SRCS}
)
target_link_libraries(goose_observer
iec61850
)

@ -1,7 +1,7 @@
LIBIEC_HOME=../..
PROJECT_BINARY_NAME = client_example3
PROJECT_SOURCES = client_example3.c
PROJECT_BINARY_NAME = goose_observer
PROJECT_SOURCES = goose_observer.c
include $(LIBIEC_HOME)/make/target_system.mk
include $(LIBIEC_HOME)/make/stack_includes.mk

@ -0,0 +1,101 @@
/*
* goose_observer.c
*
* This is an example for generic GOOSE observer
*
* Has to be started as root in Linux.
*/
#include "goose_receiver.h"
#include "goose_subscriber.h"
#include "hal_thread.h"
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
static int running = 1;
void sigint_handler(int signalId)
{
running = 0;
}
void
gooseListener(GooseSubscriber subscriber, void* parameter)
{
printf("GOOSE event:\n");
printf(" vlanTag: %s\n", GooseSubscriber_isVlanSet(subscriber) ? "found" : "NOT found");
if (GooseSubscriber_isVlanSet(subscriber))
{
printf(" vlanId: %u\n", GooseSubscriber_getVlanId(subscriber));
printf(" vlanPrio: %u\n", GooseSubscriber_getVlanPrio(subscriber));
}
printf(" appId: %d\n", GooseSubscriber_getAppId(subscriber));
uint8_t macBuf[6];
GooseSubscriber_getSrcMac(subscriber,macBuf);
printf(" srcMac: %02X:%02X:%02X:%02X:%02X:%02X\n", macBuf[0],macBuf[1],macBuf[2],macBuf[3],macBuf[4],macBuf[5]);
GooseSubscriber_getDstMac(subscriber,macBuf);
printf(" dstMac: %02X:%02X:%02X:%02X:%02X:%02X\n", macBuf[0],macBuf[1],macBuf[2],macBuf[3],macBuf[4],macBuf[5]);
printf(" goId: %s\n", GooseSubscriber_getGoId(subscriber));
printf(" goCbRef: %s\n", GooseSubscriber_getGoCbRef(subscriber));
printf(" dataSet: %s\n", GooseSubscriber_getDataSet(subscriber));
printf(" confRev: %u\n", GooseSubscriber_getConfRev(subscriber));
printf(" ndsCom: %s\n", GooseSubscriber_needsCommission(subscriber) ? "true" : "false");
printf(" simul: %s\n", GooseSubscriber_isTest(subscriber) ? "true" : "false");
printf(" stNum: %u sqNum: %u\n", GooseSubscriber_getStNum(subscriber),
GooseSubscriber_getSqNum(subscriber));
printf(" timeToLive: %u\n", GooseSubscriber_getTimeAllowedToLive(subscriber));
uint64_t timestamp = GooseSubscriber_getTimestamp(subscriber);
printf(" timestamp: %u.%u\n", (uint32_t) (timestamp / 1000), (uint32_t) (timestamp % 1000));
printf(" message is %s\n", GooseSubscriber_isValid(subscriber) ? "valid" : "INVALID");
MmsValue* values = GooseSubscriber_getDataSetValues(subscriber);
char buffer[1024];
MmsValue_printToBuffer(values, buffer, 1024);
printf(" AllData: %s\n", buffer);
}
int
main(int argc, char** argv)
{
GooseReceiver receiver = GooseReceiver_create();
if (argc > 1) {
printf("Set interface id: %s\n", argv[1]);
GooseReceiver_setInterfaceId(receiver, argv[1]);
}
else {
printf("Using interface eth0\n");
GooseReceiver_setInterfaceId(receiver, "eth0");
}
GooseSubscriber subscriber = GooseSubscriber_create("", NULL);
GooseSubscriber_setObserver(subscriber);
GooseSubscriber_setListener(subscriber, gooseListener, NULL);
GooseReceiver_addSubscriber(receiver, subscriber);
GooseReceiver_start(receiver);
if (GooseReceiver_isRunning(receiver)) {
signal(SIGINT, sigint_handler);
while (running) {
Thread_sleep(100);
}
}
else {
printf("Failed to start GOOSE subscriber. Reason can be that the Ethernet interface doesn't exist or root permission are required.\n");
}
GooseReceiver_stop(receiver);
GooseReceiver_destroy(receiver);
return 0;
}

@ -3,10 +3,12 @@ set(goose_publisher_example_SRCS
goose_publisher_example.c
)
IF(WIN32)
IF(MSVC)
set_source_files_properties(${goose_publisher_example_SRCS}
PROPERTIES LANGUAGE CXX)
ENDIF(MSVC)
add_executable(goose_publisher_example
${goose_publisher_example_SRCS}
)
@ -15,16 +17,4 @@ target_link_libraries(goose_publisher_example
iec61850
)
ELSE(WIN32)
add_executable(goose_publisher_example
${goose_publisher_example_SRCS}
)
target_link_libraries(goose_publisher_example
iec61850
)
ENDIF(WIN32)

@ -12,60 +12,77 @@
#include "goose_publisher.h"
#include "hal_thread.h"
// has to be executed as root!
/* has to be executed as root! */
int
main(int argc, char** argv)
main(int argc, char **argv)
{
char* interface;
char *interface;
if (argc > 1)
interface = argv[1];
interface = argv[1];
else
interface = "eth0";
interface = "eth0";
printf("Using interface %s\n", interface);
LinkedList dataSetValues = LinkedList_create();
LinkedList_add(dataSetValues, MmsValue_newIntegerFromInt32(1234));
LinkedList_add(dataSetValues, MmsValue_newBinaryTime(false));
LinkedList_add(dataSetValues, MmsValue_newIntegerFromInt32(5678));
CommParameters gooseCommParameters;
gooseCommParameters.appId = 1000;
gooseCommParameters.dstAddress[0] = 0x01;
gooseCommParameters.dstAddress[1] = 0x0c;
gooseCommParameters.dstAddress[2] = 0xcd;
gooseCommParameters.dstAddress[3] = 0x01;
gooseCommParameters.dstAddress[4] = 0x00;
gooseCommParameters.dstAddress[5] = 0x01;
gooseCommParameters.vlanId = 0;
gooseCommParameters.vlanPriority = 4;
/*
* Create a new GOOSE publisher instance. As the second parameter the interface
* name can be provided (e.g. "eth0" on a Linux system). If the second parameter
* is NULL the interface name as defined with CONFIG_ETHERNET_INTERFACE_ID in
* stack_config.h is used.
*/
GoosePublisher publisher = GoosePublisher_create(&gooseCommParameters, interface);
GoosePublisher_setGoCbRef(publisher, "simpleIOGenericIO/LLN0$GO$gcbAnalogValues");
GoosePublisher_setConfRev(publisher, 1);
GoosePublisher_setDataSetRef(publisher, "simpleIOGenericIO/LLN0$AnalogValues");
int i = 0;
for (i = 0; i < 3; i++) {
Thread_sleep(1000);
if (GoosePublisher_publish(publisher, dataSetValues) == -1) {
printf("Error sending message!\n");
}
}
GoosePublisher_destroy(publisher);
LinkedList dataSetValues = LinkedList_create();
LinkedList_add(dataSetValues, MmsValue_newIntegerFromInt32(1234));
LinkedList_add(dataSetValues, MmsValue_newBinaryTime(false));
LinkedList_add(dataSetValues, MmsValue_newIntegerFromInt32(5678));
CommParameters gooseCommParameters;
gooseCommParameters.appId = 1000;
gooseCommParameters.dstAddress[0] = 0x01;
gooseCommParameters.dstAddress[1] = 0x0c;
gooseCommParameters.dstAddress[2] = 0xcd;
gooseCommParameters.dstAddress[3] = 0x01;
gooseCommParameters.dstAddress[4] = 0x00;
gooseCommParameters.dstAddress[5] = 0x01;
gooseCommParameters.vlanId = 0;
gooseCommParameters.vlanPriority = 4;
/*
* Create a new GOOSE publisher instance. As the second parameter the interface
* name can be provided (e.g. "eth0" on a Linux system). If the second parameter
* is NULL the interface name as defined with CONFIG_ETHERNET_INTERFACE_ID in
* stack_config.h is used.
*/
GoosePublisher publisher = GoosePublisher_create(&gooseCommParameters, interface);
if (publisher) {
GoosePublisher_setGoCbRef(publisher, "simpleIOGenericIO/LLN0$GO$gcbAnalogValues");
GoosePublisher_setConfRev(publisher, 1);
GoosePublisher_setDataSetRef(publisher, "simpleIOGenericIO/LLN0$AnalogValues");
GoosePublisher_setTimeAllowedToLive(publisher, 500);
int i = 0;
for (i = 0; i < 4; i++) {
Thread_sleep(1000);
if (i == 3) {
/* now change dataset to send an invalid GOOSE message */
LinkedList_add(dataSetValues, MmsValue_newBoolean(true));
GoosePublisher_publish(publisher, dataSetValues);
}
else {
if (GoosePublisher_publish(publisher, dataSetValues) == -1) {
printf("Error sending message!\n");
}
}
}
GoosePublisher_destroy(publisher);
}
else {
printf("Failed to create GOOSE publisher. Reason can be that the Ethernet interface doesn't exist or root permission are required.\n");
}
LinkedList_destroyDeep(dataSetValues, (LinkedListValueDeleteFunction) MmsValue_delete);
return 0;
}

@ -3,10 +3,12 @@ set(goose_subscriber_example_SRCS
goose_subscriber_example.c
)
IF(WIN32)
IF(MSVC)
set_source_files_properties(${goose_subscriber_example_SRCS}
PROPERTIES LANGUAGE CXX)
ENDIF(MSVC)
add_executable(goose_subscriber_example
${goose_subscriber_example_SRCS}
)
@ -15,16 +17,4 @@ target_link_libraries(goose_subscriber_example
iec61850
)
ELSE(WIN32)
add_executable(goose_subscriber_example
${goose_subscriber_example_SRCS}
)
target_link_libraries(goose_subscriber_example
iec61850
)
ENDIF(WIN32)

@ -9,6 +9,7 @@
#include "goose_receiver.h"
#include "goose_subscriber.h"
#include "hal_thread.h"
#include "linked_list.h"
#include <stdlib.h>
#include <stdio.h>
@ -16,12 +17,13 @@
static int running = 1;
void sigint_handler(int signalId)
static void
sigint_handler(int signalId)
{
running = 0;
}
void
static void
gooseListener(GooseSubscriber subscriber, void* parameter)
{
printf("GOOSE event:\n");
@ -32,6 +34,7 @@ gooseListener(GooseSubscriber subscriber, void* parameter)
uint64_t timestamp = GooseSubscriber_getTimestamp(subscriber);
printf(" timestamp: %u.%u\n", (uint32_t) (timestamp / 1000), (uint32_t) (timestamp % 1000));
printf(" message is %s\n", GooseSubscriber_isValid(subscriber) ? "valid" : "INVALID");
MmsValue* values = GooseSubscriber_getDataSetValues(subscriber);
@ -39,7 +42,7 @@ gooseListener(GooseSubscriber subscriber, void* parameter)
MmsValue_printToBuffer(values, buffer, 1024);
printf("%s\n", buffer);
printf(" allData: %s\n", buffer);
}
int
@ -47,17 +50,19 @@ main(int argc, char** argv)
{
GooseReceiver receiver = GooseReceiver_create();
if (argc > 1) {
printf("Set interface id: %s\n", argv[1]);
GooseReceiver_setInterfaceId(receiver, argv[1]);
}
else {
printf("Using interface eth0\n");
GooseReceiver_setInterfaceId(receiver, "eth0");
}
if (argc > 1) {
printf("Set interface id: %s\n", argv[1]);
GooseReceiver_setInterfaceId(receiver, argv[1]);
}
else {
printf("Using interface eth0\n");
GooseReceiver_setInterfaceId(receiver, "eth0");
}
GooseSubscriber subscriber = GooseSubscriber_create("simpleIOGenericIO/LLN0$GO$gcbAnalogValues", NULL);
uint8_t dstMac[6] = {0x01,0x0c,0xcd,0x01,0x00,0x01};
GooseSubscriber_setDstMac(subscriber, dstMac);
GooseSubscriber_setAppId(subscriber, 1000);
GooseSubscriber_setListener(subscriber, gooseListener, NULL);
@ -66,13 +71,20 @@ main(int argc, char** argv)
GooseReceiver_start(receiver);
signal(SIGINT, sigint_handler);
if (GooseReceiver_isRunning(receiver)) {
signal(SIGINT, sigint_handler);
while (running) {
Thread_sleep(100);
while (running) {
Thread_sleep(100);
}
}
else {
printf("Failed to start GOOSE subscriber. Reason can be that the Ethernet interface doesn't exist or root permission are required.\n");
}
GooseReceiver_stop(receiver);
GooseReceiver_destroy(receiver);
return 0;
}

@ -7,10 +7,10 @@ set(sv_9_2_LE_example_SRCS
static_model.c
)
IF(WIN32)
IF(MSVC)
set_source_files_properties(${sv_9_2_LE_example_SRCS}
PROPERTIES LANGUAGE CXX)
ENDIF(WIN32)
ENDIF(MSVC)
add_executable(sv_9_2_LE_example
${sv_9_2_LE_example_SRCS}

@ -9,6 +9,8 @@ PROJECT_ICD_FILE = sv.icd
include $(LIBIEC_HOME)/make/target_system.mk
include $(LIBIEC_HOME)/make/stack_includes.mk
LDFLAGS += -lm
all: $(PROJECT_BINARY_NAME)
include $(LIBIEC_HOME)/make/common_targets.mk

@ -28,13 +28,12 @@
#include <stdlib.h>
#include <stdio.h>
#define _USE_MATH_DEFINES
#include <math.h>
/* Include the generated header with the model access handles */
#include "static_model.h"
/* import IEC 61850 device model created from SCL-File */
extern IedModel iedModel;
static int running = 0;
static int svcbEnabled = 1;
@ -48,11 +47,21 @@ static int amp2;
static int amp3;
static int amp4;
static int amp1q;
static int amp2q;
static int amp3q;
static int amp4q;
static int vol1;
static int vol2;
static int vol3;
static int vol4;
static int vol1q;
static int vol2q;
static int vol3q;
static int vol4q;
static SVPublisher svPublisher;
static SVPublisher_ASDU asdu;
@ -61,19 +70,33 @@ setupSVPublisher(const char* svInterface)
{
svPublisher = SVPublisher_create(NULL, svInterface);
asdu = SVPublisher_addASDU(svPublisher, "xxxxMUnn01", NULL, 1);
if (svPublisher) {
amp1 = SVPublisher_ASDU_addINT32(asdu);
amp2 = SVPublisher_ASDU_addINT32(asdu);
amp3 = SVPublisher_ASDU_addINT32(asdu);
amp4 = SVPublisher_ASDU_addINT32(asdu);
asdu = SVPublisher_addASDU(svPublisher, "xxxxMUnn01", NULL, 1);
vol1 = SVPublisher_ASDU_addINT32(asdu);
vol2 = SVPublisher_ASDU_addINT32(asdu);
vol3 = SVPublisher_ASDU_addINT32(asdu);
vol4 = SVPublisher_ASDU_addINT32(asdu);
amp1 = SVPublisher_ASDU_addINT32(asdu);
amp1q = SVPublisher_ASDU_addQuality(asdu);
amp2 = SVPublisher_ASDU_addINT32(asdu);
amp2q = SVPublisher_ASDU_addQuality(asdu);
amp3 = SVPublisher_ASDU_addINT32(asdu);
amp3q = SVPublisher_ASDU_addQuality(asdu);
amp4 = SVPublisher_ASDU_addINT32(asdu);
amp4q = SVPublisher_ASDU_addQuality(asdu);
SVPublisher_setupComplete(svPublisher);
vol1 = SVPublisher_ASDU_addINT32(asdu);
vol1q = SVPublisher_ASDU_addQuality(asdu);
vol2 = SVPublisher_ASDU_addINT32(asdu);
vol2q = SVPublisher_ASDU_addQuality(asdu);
vol3 = SVPublisher_ASDU_addINT32(asdu);
vol3q = SVPublisher_ASDU_addQuality(asdu);
vol4 = SVPublisher_ASDU_addINT32(asdu);
vol4q = SVPublisher_ASDU_addQuality(asdu);
SVPublisher_ASDU_setSmpCntWrap(asdu, 4000);
SVPublisher_ASDU_setRefrTm(asdu, 0);
SVPublisher_setupComplete(svPublisher);
}
}
static void sVCBEventHandler (SVControlBlock* svcb, int event, void* parameter)
@ -111,57 +134,121 @@ main(int argc, char** argv)
setupSVPublisher(svInterface);
int voltage = 1;
int current = 1;
if (svPublisher) {
SVControlBlock* svcb = IedModel_getSVControlBlock(&iedModel, IEDMODEL_MUnn_LLN0, "MSVCB01");
SVControlBlock* svcb = IedModel_getSVControlBlock(&iedModel, IEDMODEL_MUnn_LLN0, "MSVCB01");
if (svcb == NULL) {
printf("Lookup svcb failed!\n");
exit(1);
}
if (svcb == NULL) {
printf("Lookup svcb failed!\n");
exit(1);
}
IedServer_setSVCBHandler(iedServer, svcb, sVCBEventHandler, NULL);
IedServer_setSVCBHandler(iedServer, svcb, sVCBEventHandler, NULL);
while (running) {
Quality q = QUALITY_VALIDITY_GOOD;
uint64_t timeval = Hal_getTimeInMs();
int vol = (int) (6350.f * sqrt(2));
int amp = 0;
float phaseAngle = 0.f;
IedServer_lockDataModel(iedServer);
int voltageA;
int voltageB;
int voltageC;
int voltageN;
int currentA;
int currentB;
int currentC;
int currentN;
IedServer_updateInt32AttributeValue(iedServer, IEDMODEL_MUnn_TCTR1_Amp_instMag_i, current);
IedServer_updateInt32AttributeValue(iedServer, IEDMODEL_MUnn_TCTR2_Amp_instMag_i, current);
IedServer_updateInt32AttributeValue(iedServer, IEDMODEL_MUnn_TCTR3_Amp_instMag_i, current);
IedServer_updateInt32AttributeValue(iedServer, IEDMODEL_MUnn_TCTR3_Amp_instMag_i, current);
int sampleCount = 0;
IedServer_updateInt32AttributeValue(iedServer, IEDMODEL_MUnn_TVTR1_Vol_instMag_i, voltage);
IedServer_updateInt32AttributeValue(iedServer, IEDMODEL_MUnn_TVTR2_Vol_instMag_i, voltage);
IedServer_updateInt32AttributeValue(iedServer, IEDMODEL_MUnn_TVTR3_Vol_instMag_i, voltage);
IedServer_updateInt32AttributeValue(iedServer, IEDMODEL_MUnn_TVTR4_Vol_instMag_i, voltage);
uint64_t nextCycleStart = Hal_getTimeInMs() + 1000;
IedServer_unlockDataModel(iedServer);
while (running) {
if (svcbEnabled) {
/* update measurement values */
int samplePoint = sampleCount % 80;
SVPublisher_ASDU_setINT32(asdu, amp1, current);
SVPublisher_ASDU_setINT32(asdu, amp2, current);
SVPublisher_ASDU_setINT32(asdu, amp3, current);
SVPublisher_ASDU_setINT32(asdu, amp4, current);
double angleA = (2 * M_PI / 80) * samplePoint;
double angleB = (2 * M_PI / 80) * samplePoint - ( 2 * M_PI / 3);
double angleC = (2 * M_PI / 80) * samplePoint - ( 4 * M_PI / 3);
SVPublisher_ASDU_setINT32(asdu, vol1, voltage);
SVPublisher_ASDU_setINT32(asdu, vol2, voltage);
SVPublisher_ASDU_setINT32(asdu, vol3, voltage);
SVPublisher_ASDU_setINT32(asdu, vol4, voltage);
voltageA = (vol * sin(angleA)) * 100;
voltageB = (vol * sin(angleB)) * 100;
voltageC = (vol * sin(angleC)) * 100;
voltageN = voltageA + voltageB + voltageC;
SVPublisher_ASDU_increaseSmpCnt(asdu);
currentA = (amp * sin(angleA - phaseAngle)) * 1000;
currentB = (amp * sin(angleB - phaseAngle)) * 1000;
currentC = (amp * sin(angleC - phaseAngle)) * 1000;
currentN = currentA + currentB + currentC;
SVPublisher_publish(svPublisher);
}
IedServer_lockDataModel(iedServer);
IedServer_updateInt32AttributeValue(iedServer, IEDMODEL_MUnn_TCTR1_Amp_instMag_i, currentA);
IedServer_updateQuality(iedServer, IEDMODEL_MUnn_TCTR1_Amp_q, q);
IedServer_updateInt32AttributeValue(iedServer, IEDMODEL_MUnn_TCTR2_Amp_instMag_i, currentB);
IedServer_updateQuality(iedServer, IEDMODEL_MUnn_TCTR2_Amp_q, q);
IedServer_updateInt32AttributeValue(iedServer, IEDMODEL_MUnn_TCTR3_Amp_instMag_i, currentC);
IedServer_updateQuality(iedServer, IEDMODEL_MUnn_TCTR3_Amp_q, q);
IedServer_updateInt32AttributeValue(iedServer, IEDMODEL_MUnn_TCTR4_Amp_instMag_i, currentN);
IedServer_updateQuality(iedServer, IEDMODEL_MUnn_TCTR4_Amp_q, q);
IedServer_updateInt32AttributeValue(iedServer, IEDMODEL_MUnn_TVTR1_Vol_instMag_i, voltageA);
IedServer_updateQuality(iedServer, IEDMODEL_MUnn_TVTR1_Vol_q, q);
IedServer_updateInt32AttributeValue(iedServer, IEDMODEL_MUnn_TVTR2_Vol_instMag_i, voltageB);
IedServer_updateQuality(iedServer, IEDMODEL_MUnn_TVTR2_Vol_q, q);
IedServer_updateInt32AttributeValue(iedServer, IEDMODEL_MUnn_TVTR3_Vol_instMag_i, voltageC);
IedServer_updateQuality(iedServer, IEDMODEL_MUnn_TVTR3_Vol_q, q);
IedServer_updateInt32AttributeValue(iedServer, IEDMODEL_MUnn_TVTR4_Vol_instMag_i, voltageN);
IedServer_updateQuality(iedServer, IEDMODEL_MUnn_TVTR4_Vol_q, q);
IedServer_unlockDataModel(iedServer);
voltage++;
current++;
if (svcbEnabled) {
Thread_sleep(500);
SVPublisher_ASDU_setINT32(asdu, amp1, currentA);
SVPublisher_ASDU_setQuality(asdu, amp1q, q);
SVPublisher_ASDU_setINT32(asdu, amp2, currentB);
SVPublisher_ASDU_setQuality(asdu, amp2q, q);
SVPublisher_ASDU_setINT32(asdu, amp3, currentC);
SVPublisher_ASDU_setQuality(asdu, amp3q, q);
SVPublisher_ASDU_setINT32(asdu, amp4, currentN);
SVPublisher_ASDU_setQuality(asdu, amp4q, q);
SVPublisher_ASDU_setINT32(asdu, vol1, voltageA);
SVPublisher_ASDU_setQuality(asdu, vol1q, q);
SVPublisher_ASDU_setINT32(asdu, vol2, voltageB);
SVPublisher_ASDU_setQuality(asdu, vol2q, q);
SVPublisher_ASDU_setINT32(asdu, vol3, voltageC);
SVPublisher_ASDU_setQuality(asdu, vol3q, q);
SVPublisher_ASDU_setINT32(asdu, vol4, voltageN);
SVPublisher_ASDU_setQuality(asdu, vol4q, q);
SVPublisher_ASDU_setRefrTmNs(asdu, Hal_getTimeInNs());
SVPublisher_ASDU_setSmpCnt(asdu, (uint16_t) sampleCount);
SVPublisher_publish(svPublisher);
}
sampleCount = ((sampleCount + 1) % 4000);
if ((sampleCount % 400) == 0) {
uint64_t timeval = Hal_getTimeInMs();
while (timeval < nextCycleStart + 100) {
Thread_sleep(1);
timeval = Hal_getTimeInMs();
}
nextCycleStart = nextCycleStart + 100;
}
}
}
else {
printf("Cannot start SV publisher!\n");
}
/* stop MMS server - close TCP server socket and all client sockets */

@ -22,7 +22,7 @@ extern DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda7;
DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda0 = {
"MUnn",
false,
"TCTR1$MX$Amp$instMag$i",
"TCTR1$MX$Amp",
-1,
NULL,
NULL,
@ -32,7 +32,7 @@ DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda0 = {
DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda1 = {
"MUnn",
false,
"TCTR2$MX$Amp$instMag$i",
"TCTR2$MX$Amp",
-1,
NULL,
NULL,
@ -42,7 +42,7 @@ DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda1 = {
DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda2 = {
"MUnn",
false,
"TCTR3$MX$Amp$instMag$i",
"TCTR3$MX$Amp",
-1,
NULL,
NULL,
@ -52,7 +52,7 @@ DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda2 = {
DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda3 = {
"MUnn",
false,
"TCTR4$MX$Amp$instMag$i",
"TCTR4$MX$Amp",
-1,
NULL,
NULL,
@ -62,7 +62,7 @@ DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda3 = {
DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda4 = {
"MUnn",
false,
"TVTR1$MX$Vol$instMag$i",
"TVTR1$MX$Vol",
-1,
NULL,
NULL,
@ -72,7 +72,7 @@ DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda4 = {
DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda5 = {
"MUnn",
false,
"TVTR2$MX$Vol$instMag$i",
"TVTR2$MX$Vol",
-1,
NULL,
NULL,
@ -82,7 +82,7 @@ DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda5 = {
DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda6 = {
"MUnn",
false,
"TVTR3$MX$Vol$instMag$i",
"TVTR3$MX$Vol",
-1,
NULL,
NULL,
@ -92,7 +92,7 @@ DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda6 = {
DataSetEntry iedModelds_MUnn_LLN0_PhsMeas1_fcda7 = {
"MUnn",
false,
"TVTR4$MX$Vol$instMag$i",
"TVTR4$MX$Vol",
-1,
NULL,
NULL,

@ -74,26 +74,26 @@ SCL.xsd">
<DataSet name="PhsMeas1">
<FCDA ldInst="MUnn" lnClass="TCTR" lnInst="1" fc="MX"
doName="Amp" daName="instMag.i"/>
doName="Amp" />
<FCDA ldInst="MUnn" lnClass="TCTR" lnInst="2" fc="MX"
doName="Amp" daName="instMag.i"/>
doName="Amp" />
<FCDA ldInst="MUnn" lnClass="TCTR" lnInst="3" fc="MX"
doName="Amp" daName="instMag.i"/>
doName="Amp" />
<FCDA ldInst="MUnn" lnClass="TCTR" lnInst="4" fc="MX"
doName="Amp" daName="instMag.i"/>
doName="Amp" />
<FCDA ldInst="MUnn" lnClass="TVTR" lnInst="1" fc="MX"
doName="Vol" daName="instMag.i"/>
doName="Vol" />
<FCDA ldInst="MUnn" lnClass="TVTR" lnInst="2" fc="MX"
doName="Vol" daName="instMag.i"/>
doName="Vol" />
<FCDA ldInst="MUnn" lnClass="TVTR" lnInst="3" fc="MX"
doName="Vol" daName="instMag.i"/>
doName="Vol" />
<FCDA ldInst="MUnn" lnClass="TVTR" lnInst="4" fc="MX"
doName="Vol" daName="instMag.i"/>
doName="Vol" />
</DataSet>
<SampledValueControl name="MSVCB01" datSet="PhsMeas1"
smvID="xxxxMUnn01" smpRate="80" nofASDU="1" confRev="1">
smvID="xxxxMUnn01" smpRate="80" nofASDU="1" confRev="1" smpMod="SmpPerPeriod">
<SmvOpts refreshTime="false" sampleSynchronized="true"
security="false" dataRef="false" />

@ -3,10 +3,10 @@ set(iec61850_client_example1_SRCS
client_example1.c
)
IF(WIN32)
IF(MSVC)
set_source_files_properties(${iec61850_client_example1_SRCS}
PROPERTIES LANGUAGE CXX)
ENDIF(WIN32)
ENDIF(MSVC)
add_executable(iec61850_client_example1
${iec61850_client_example1_SRCS}

@ -33,6 +33,9 @@ int main(int argc, char** argv) {
char* hostname;
int tcpPort = 102;
const char* localIp = NULL;
int localTcpPort = -1;
if (argc > 1)
hostname = argv[1];
@ -42,20 +45,42 @@ int main(int argc, char** argv) {
if (argc > 2)
tcpPort = atoi(argv[2]);
if (argc > 3)
localIp = argv[3];
if (argc > 4)
localTcpPort = atoi(argv[4]);
IedClientError error;
IedConnection con = IedConnection_create();
/* Optional bind to local IP address/interface */
if (localIp) {
IedConnection_setLocalAddress(con, localIp, localTcpPort);
printf("Bound to Local Address: %s:%i\n", localIp, localTcpPort);
}
IedConnection_connect(con, &error, hostname, tcpPort);
printf("Connecting to %s:%i\n", hostname, tcpPort);
if (error == IED_ERROR_OK) {
if (error == IED_ERROR_OK)
{
printf("Connected\n");
/* read an analog measurement value from server */
MmsValue* value = IedConnection_readObject(con, &error, "simpleIOGenericIO/GGIO1.AnIn1.mag.f", IEC61850_FC_MX);
if (value != NULL) {
float fval = MmsValue_toFloat(value);
printf("read float value: %f\n", fval);
if (value != NULL)
{
if (MmsValue_getType(value) == MMS_FLOAT) {
float fval = MmsValue_toFloat(value);
printf("read float value: %f\n", fval);
}
else if (MmsValue_getType(value) == MMS_DATA_ACCESS_ERROR) {
printf("Failed to read value (error code: %i)\n", MmsValue_getDataAccessError(value));
}
MmsValue_delete(value);
}
@ -64,62 +89,64 @@ int main(int argc, char** argv) {
IedConnection_writeObject(con, &error, "simpleIOGenericIO/GGIO1.NamPlt.vendor", IEC61850_FC_DC, value);
if (error != IED_ERROR_OK)
printf("failed to write simpleIOGenericIO/GGIO1.NamPlt.vendor!\n");
printf("failed to write simpleIOGenericIO/GGIO1.NamPlt.vendor! (error code: %i)\n", error);
MmsValue_delete(value);
/* read data set */
ClientDataSet clientDataSet = IedConnection_readDataSetValues(con, &error, "simpleIOGenericIO/LLN0.Events", NULL);
if (clientDataSet == NULL)
if (clientDataSet == NULL) {
printf("failed to read dataset\n");
goto close_connection;
}
/* Read RCB values */
ClientReportControlBlock rcb =
IedConnection_getRCBValues(con, &error, "simpleIOGenericIO/LLN0.RP.EventsRCB01", NULL);
if (rcb) {
bool rptEna = ClientReportControlBlock_getRptEna(rcb);
bool rptEna = ClientReportControlBlock_getRptEna(rcb);
printf("RptEna = %i\n", rptEna);
printf("RptEna = %i\n", rptEna);
/* Install handler for reports */
IedConnection_installReportHandler(con, "simpleIOGenericIO/LLN0.RP.EventsRCB01",
ClientReportControlBlock_getRptId(rcb), reportCallbackFunction, NULL);
/* Install handler for reports */
IedConnection_installReportHandler(con, "simpleIOGenericIO/LLN0.RP.EventsRCB01",
ClientReportControlBlock_getRptId(rcb), reportCallbackFunction, NULL);
/* Set trigger options and enable report */
ClientReportControlBlock_setTrgOps(rcb, TRG_OPT_DATA_UPDATE | TRG_OPT_INTEGRITY | TRG_OPT_GI);
ClientReportControlBlock_setRptEna(rcb, true);
ClientReportControlBlock_setIntgPd(rcb, 5000);
IedConnection_setRCBValues(con, &error, rcb, RCB_ELEMENT_RPT_ENA | RCB_ELEMENT_TRG_OPS | RCB_ELEMENT_INTG_PD, true);
/* Set trigger options and enable report */
ClientReportControlBlock_setTrgOps(rcb, TRG_OPT_DATA_UPDATE | TRG_OPT_INTEGRITY | TRG_OPT_GI);
ClientReportControlBlock_setRptEna(rcb, true);
ClientReportControlBlock_setIntgPd(rcb, 5000);
IedConnection_setRCBValues(con, &error, rcb, RCB_ELEMENT_RPT_ENA | RCB_ELEMENT_TRG_OPS | RCB_ELEMENT_INTG_PD, true);
if (error != IED_ERROR_OK)
printf("report activation failed (code: %i)\n", error);
if (error != IED_ERROR_OK)
printf("report activation failed (code: %i)\n", error);
Thread_sleep(1000);
Thread_sleep(1000);
/* trigger GI report */
ClientReportControlBlock_setGI(rcb, true);
IedConnection_setRCBValues(con, &error, rcb, RCB_ELEMENT_GI, true);
/* trigger GI report */
ClientReportControlBlock_setGI(rcb, true);
IedConnection_setRCBValues(con, &error, rcb, RCB_ELEMENT_GI, true);
if (error != IED_ERROR_OK)
printf("Error triggering a GI report (code: %i)\n", error);
if (error != IED_ERROR_OK)
printf("Error triggering a GI report (code: %i)\n", error);
Thread_sleep(60000);
Thread_sleep(60000);
/* disable reporting */
ClientReportControlBlock_setRptEna(rcb, false);
IedConnection_setRCBValues(con, &error, rcb, RCB_ELEMENT_RPT_ENA, true);
/* disable reporting */
ClientReportControlBlock_setRptEna(rcb, false);
IedConnection_setRCBValues(con, &error, rcb, RCB_ELEMENT_RPT_ENA, true);
if (error != IED_ERROR_OK)
printf("disable reporting failed (code: %i)\n", error);
if (error != IED_ERROR_OK)
printf("disable reporting failed (code: %i)\n", error);
ClientDataSet_destroy(clientDataSet);
ClientDataSet_destroy(clientDataSet);
ClientReportControlBlock_destroy(rcb);
ClientReportControlBlock_destroy(rcb);
}
close_connection:
close_connection:
IedConnection_close(con);
}
@ -128,6 +155,6 @@ int main(int argc, char** argv) {
}
IedConnection_destroy(con);
}
return 0;
}

@ -3,10 +3,10 @@ set(iec61850_client_example2_SRCS
client_example2.c
)
IF(WIN32)
IF(MSVC)
set_source_files_properties(${iec61850_client_example2_SRCS}
PROPERTIES LANGUAGE CXX)
ENDIF(WIN32)
ENDIF(MSVC)
add_executable(iec61850_client_example2
${iec61850_client_example2_SRCS}

@ -38,7 +38,7 @@ printDataDirectory(char* doRef, IedConnection con, int spaces)
dataAttribute = LinkedList_getNext(dataAttribute);
char daRef[129];
char daRef[130];
sprintf(daRef, "%s.%s", doRef, daName);
printDataDirectory(daRef, con, spaces + 2);
}
@ -124,7 +124,7 @@ main(int argc, char** argv)
while (dataSet != NULL) {
char* dataSetName = (char*) dataSet->data;
bool isDeletable;
char dataSetRef[129];
char dataSetRef[130];
sprintf(dataSetRef, "%s.%s", lnRef, dataSetName);
LinkedList dataSetMembers = IedConnection_getDataSetDirectory(con, &error, dataSetRef,
@ -201,5 +201,6 @@ main(int argc, char** argv)
cleanup_and_exit:
IedConnection_destroy(con);
return 0;
}

@ -1,17 +0,0 @@
set(iec61850_client_example3_SRCS
client_example3.c
)
IF(WIN32)
set_source_files_properties(${iec61850_client_example3_SRCS}
PROPERTIES LANGUAGE CXX)
ENDIF(WIN32)
add_executable(iec61850_client_example3
${iec61850_client_example3_SRCS}
)
target_link_libraries(iec61850_client_example3
iec61850
)

@ -1,219 +0,0 @@
/*
* client_example3.c
*
* How to control a device ... intended to be used with server_example_control
*/
#include "iec61850_client.h"
#include "hal_thread.h"
#include <stdlib.h>
#include <stdio.h>
static void commandTerminationHandler(void *parameter, ControlObjectClient connection)
{
LastApplError lastApplError = ControlObjectClient_getLastApplError(connection);
// if lastApplError.error != 0 this indicates a CommandTermination-
if (lastApplError.error != 0) {
printf("Received CommandTermination-.\n");
printf(" LastApplError: %i\n", lastApplError.error);
printf(" addCause: %i\n", lastApplError.addCause);
}
else
printf("Received CommandTermination+.\n");
}
int main(int argc, char** argv) {
char* hostname;
int tcpPort = 102;
if (argc > 1)
hostname = argv[1];
else
hostname = "localhost";
if (argc > 2)
tcpPort = atoi(argv[2]);
IedClientError error;
IedConnection con = IedConnection_create();
IedConnection_connect(con, &error, hostname, tcpPort);
if (error == IED_ERROR_OK) {
/************************
* Direct control
***********************/
ControlObjectClient control
= ControlObjectClient_create("simpleIOGenericIO/GGIO1.SPCSO1", con);
MmsValue* ctlVal = MmsValue_newBoolean(true);
ControlObjectClient_setOrigin(control, NULL, 3);
if (ControlObjectClient_operate(control, ctlVal, 0 /* operate now */)) {
printf("simpleIOGenericIO/GGIO1.SPCSO1 operated successfully\n");
}
else {
printf("failed to operate simpleIOGenericIO/GGIO1.SPCSO1\n");
}
MmsValue_delete(ctlVal);
ControlObjectClient_destroy(control);
/* Check if status value has changed */
MmsValue* stVal = IedConnection_readObject(con, &error, "simpleIOGenericIO/GGIO1.SPCSO1.stVal", IEC61850_FC_ST);
if (error == IED_ERROR_OK) {
bool state = MmsValue_getBoolean(stVal);
MmsValue_delete(stVal);
printf("New status of simpleIOGenericIO/GGIO1.SPCSO1.stVal: %i\n", state);
}
else {
printf("Reading status for simpleIOGenericIO/GGIO1.SPCSO1 failed!\n");
}
/************************
* Select before operate
***********************/
control = ControlObjectClient_create("simpleIOGenericIO/GGIO1.SPCSO2", con);
if (ControlObjectClient_select(control)) {
ctlVal = MmsValue_newBoolean(true);
if (ControlObjectClient_operate(control, ctlVal, 0 /* operate now */)) {
printf("simpleIOGenericIO/GGIO1.SPCSO2 operated successfully\n");
}
else {
printf("failed to operate simpleIOGenericIO/GGIO1.SPCSO2!\n");
}
MmsValue_delete(ctlVal);
}
else {
printf("failed to select simpleIOGenericIO/GGIO1.SPCSO2!\n");
}
ControlObjectClient_destroy(control);
/****************************************
* Direct control with enhanced security
****************************************/
control = ControlObjectClient_create("simpleIOGenericIO/GGIO1.SPCSO3", con);
ControlObjectClient_setCommandTerminationHandler(control, commandTerminationHandler, NULL);
ctlVal = MmsValue_newBoolean(true);
if (ControlObjectClient_operate(control, ctlVal, 0 /* operate now */)) {
printf("simpleIOGenericIO/GGIO1.SPCSO3 operated successfully\n");
}
else {
printf("failed to operate simpleIOGenericIO/GGIO1.SPCSO3\n");
}
MmsValue_delete(ctlVal);
/* Wait for command termination message */
Thread_sleep(1000);
ControlObjectClient_destroy(control);
/* Check if status value has changed */
stVal = IedConnection_readObject(con, &error, "simpleIOGenericIO/GGIO1.SPCSO3.stVal", IEC61850_FC_ST);
if (error == IED_ERROR_OK) {
bool state = MmsValue_getBoolean(stVal);
printf("New status of simpleIOGenericIO/GGIO1.SPCSO3.stVal: %i\n", state);
MmsValue_delete(stVal);
}
else {
printf("Reading status for simpleIOGenericIO/GGIO1.SPCSO3 failed!\n");
}
/***********************************************
* Select before operate with enhanced security
***********************************************/
control = ControlObjectClient_create("simpleIOGenericIO/GGIO1.SPCSO4", con);
ControlObjectClient_setCommandTerminationHandler(control, commandTerminationHandler, NULL);
ctlVal = MmsValue_newBoolean(true);
if (ControlObjectClient_selectWithValue(control, ctlVal)) {
if (ControlObjectClient_operate(control, ctlVal, 0 /* operate now */)) {
printf("simpleIOGenericIO/GGIO1.SPCSO4 operated successfully\n");
}
else {
printf("failed to operate simpleIOGenericIO/GGIO1.SPCSO4!\n");
}
}
else {
printf("failed to select simpleIOGenericIO/GGIO1.SPCSO4!\n");
}
MmsValue_delete(ctlVal);
/* Wait for command termination message */
Thread_sleep(1000);
ControlObjectClient_destroy(control);
/*********************************************************************
* Direct control with enhanced security (expect CommandTermination-)
*********************************************************************/
control = ControlObjectClient_create("simpleIOGenericIO/GGIO1.SPCSO9", con);
ControlObjectClient_setCommandTerminationHandler(control, commandTerminationHandler, NULL);
ctlVal = MmsValue_newBoolean(true);
if (ControlObjectClient_operate(control, ctlVal, 0 /* operate now */)) {
printf("simpleIOGenericIO/GGIO1.SPCSO9 operated successfully\n");
}
else {
printf("failed to operate simpleIOGenericIO/GGIO1.SPCSO9\n");
}
MmsValue_delete(ctlVal);
/* Wait for command termination message */
Thread_sleep(1000);
ControlObjectClient_destroy(control);
IedConnection_close(con);
}
else {
printf("Connection failed!\n");
}
IedConnection_destroy(con);
}

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

Loading…
Cancel
Save