diff --git a/examples/r_goose_publisher_example/CMakeLists.txt b/examples/r_goose_publisher_example/CMakeLists.txt new file mode 100644 index 00000000..628b9aad --- /dev/null +++ b/examples/r_goose_publisher_example/CMakeLists.txt @@ -0,0 +1,20 @@ + +set(r_goose_publisher_example_SRCS + r_goose_publisher_example.c +) + +IF(MSVC) + +set_source_files_properties(${r_goose_publisher_example_SRCS} + PROPERTIES LANGUAGE CXX) +ENDIF(MSVC) + +add_executable(r_goose_publisher_example + ${r_goose_publisher_example_SRCS} +) + +target_link_libraries(r_goose_publisher_example + iec61850 +) + + diff --git a/examples/r_goose_publisher_example/r_goose_publisher_example.c b/examples/r_goose_publisher_example/r_goose_publisher_example.c new file mode 100644 index 00000000..5d7ca294 --- /dev/null +++ b/examples/r_goose_publisher_example/r_goose_publisher_example.c @@ -0,0 +1,106 @@ +/* + * r_goose_publisher_example.c + */ + +#include +#include +#include +#include +#include +#include + +#include "mms_value.h" +#include "goose_publisher.h" +#include "hal_thread.h" + +static bool running = true; + +static void +sigint_handler(int signalId) +{ + running = false; +} + +/* has to be executed as root! */ +int +main(int argc, char **argv) +{ + char* dstAddress; + + if (argc > 1) + dstAddress = argv[1]; + else + dstAddress = "230.0.10.11"; + + printf("Using destination address %s\n", dstAddress); + + RSession rSession = RSession_create(); + + if (rSession) { + + signal(SIGINT, sigint_handler); + + RSession_setRemoteAddress(rSession, dstAddress, 102); + + LinkedList dataSetValues = LinkedList_create(); + + int intVal = 1234; + + MmsValue* mmsIntVal = MmsValue_newIntegerFromInt32(intVal); + MmsValue* mmsTimeValue = MmsValue_newBinaryTime(false); + MmsValue_setBinaryTime(mmsTimeValue, Hal_getTimeInMs()); + + LinkedList_add(dataSetValues, mmsIntVal); + LinkedList_add(dataSetValues, mmsTimeValue); + LinkedList_add(dataSetValues, MmsValue_newIntegerFromInt32(5678)); + + GoosePublisher publisher = GoosePublisher_createRemote(rSession, 0x4001); + + //char* key = "0123456789ABCDEF"; + char* key = "0123456789ABCDEF"; + + RSession_addKey(rSession, 1, key, 16, R_SESSION_SEC_ALGO_AES_128_GCM, R_SESSION_SIG_ALGO_NONE); + RSession_setActiveKey(rSession, 1); + + if (publisher) { + GoosePublisher_setGoCbRef(publisher, "simpleIOGenericIO/LLN0$GO$gcbAnalogValues"); + GoosePublisher_setConfRev(publisher, 1); + GoosePublisher_setDataSetRef(publisher, "simpleIOGenericIO/LLN0$AnalogValues"); + GoosePublisher_setTimeAllowedToLive(publisher, 500); + + while (running) { + int i = 0; + + for (i = 0; i < 6; i++) { + Thread_sleep(200); + + if (i == 5) { + MmsValue_setInt32(mmsIntVal, ++intVal); + MmsValue_setBinaryTime(mmsTimeValue, Hal_getTimeInMs()); + GoosePublisher_increaseStNum(publisher); + } + + if (GoosePublisher_publish(publisher, dataSetValues) == -1) { + printf("Error sending message!\n"); + } + + if (running == false) + break; + } + } + + 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; +} + + + + diff --git a/examples/r_goose_receiver_example/CMakeLists.txt b/examples/r_goose_receiver_example/CMakeLists.txt new file mode 100644 index 00000000..ff2585f0 --- /dev/null +++ b/examples/r_goose_receiver_example/CMakeLists.txt @@ -0,0 +1,20 @@ + +set(r_goose_subscriber_example_SRCS + r_goose_subscriber_example.c +) + +IF(MSVC) + +set_source_files_properties(${r_goose_subscriber_example_SRCS} + PROPERTIES LANGUAGE CXX) +ENDIF(MSVC) + +add_executable(r_goose_subscriber_example + ${r_goose_subscriber_example_SRCS} +) + +target_link_libraries(r_goose_subscriber_example + iec61850 +) + + diff --git a/examples/r_goose_receiver_example/r_goose_subscriber_example.c b/examples/r_goose_receiver_example/r_goose_subscriber_example.c new file mode 100644 index 00000000..f70a71a9 --- /dev/null +++ b/examples/r_goose_receiver_example/r_goose_subscriber_example.c @@ -0,0 +1,94 @@ +/* + * goose_subscriber_example.c + * + * This is an example for a standalone GOOSE subscriber + * + * Has to be started as root in Linux. + */ + +#include "goose_receiver.h" +#include "goose_subscriber.h" +#include "hal_thread.h" +#include "linked_list.h" + +#include +#include +#include + +static bool running = true; + +static void +sigint_handler(int signalId) +{ + running = false; +} + +static void +gooseListener(GooseSubscriber subscriber, void* parameter) +{ + printf("GOOSE event:\n"); + 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) +{ + RSession sessionP = RSession_create(); + + if (sessionP) { + + RSession_setRemoteAddress(sessionP, "127.0.0.1", 102); + RSession_setLocalAddress(sessionP, "0.0.0.0", 102); + char* key = "0123456789ABCDEF"; + + RSession_addKey(sessionP, 1, key, 16, R_SESSION_SEC_ALGO_AES_128_GCM, R_SESSION_SIG_ALGO_NONE); + + RSession_addMulticastGroup(sessionP, "230.0.10.11"); + + GooseReceiver receiver = GooseReceiver_createRemote(sessionP); + + 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); + + 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; +} diff --git a/examples/rsv_publisher_example/CMakeLists.txt b/examples/rsv_publisher_example/CMakeLists.txt new file mode 100644 index 00000000..42c1d723 --- /dev/null +++ b/examples/rsv_publisher_example/CMakeLists.txt @@ -0,0 +1,28 @@ + +set(r_sv_publisher_example_SRCS + r_sv_publisher_example.c +) + +IF(WIN32) + +set_source_files_properties(${r_sv_publisher_example_SRCS} + PROPERTIES LANGUAGE CXX) +add_executable(r_sv_publisher_example + ${r_sv_publisher_example_SRCS} +) + +target_link_libraries(r_sv_publisher_example + iec61850 +) + +ELSE(WIN32) + +add_executable(r_sv_publisher_example + ${r_sv_publisher_example_SRCS} +) + +target_link_libraries(r_sv_publisher_example + iec61850 +) + +ENDIF(WIN32) diff --git a/examples/rsv_publisher_example/r_sv_publisher_example.c b/examples/rsv_publisher_example/r_sv_publisher_example.c new file mode 100644 index 00000000..f9c9a12b --- /dev/null +++ b/examples/rsv_publisher_example/r_sv_publisher_example.c @@ -0,0 +1,112 @@ +/* + * r-sv-example.c + */ + +#include +#include + +#include "sv_publisher.h" +#include "hal_thread.h" + +static bool running = true; + +static void +sigint_handler(int signalId) +{ + running = false; +} + +int +main(int argc, char** argv) +{ + RSession rSession = RSession_create(); + + if (rSession) { + + //RSession_setRemoteAddress(sessionP, "192.168.56.101", 102); + //RSession_setRemoteAddress(rSession, "192.168.2.227", 102); + RSession_setRemoteAddress(rSession, "230.0.10.10", 102); + + SVPublisher svPublisher = SVPublisher_createRemote(rSession, 0x4000); + + uint32_t activeKeyId = 1; + uint64_t nextKeyChangeTime = Hal_getTimeInMs() + 5000; + + if (svPublisher) { + + signal(SIGINT, sigint_handler); + + char* key1 = "0123456789ABCDEF"; + char* key2 = "FEDCBA9876543210"; + + RSession_addKey(rSession, 1, key1, 16, R_SESSION_SEC_ALGO_AES_128_GCM, R_SESSION_SIG_ALGO_NONE); + RSession_addKey(rSession, 2, key2, 16, R_SESSION_SEC_ALGO_AES_128_GCM, R_SESSION_SIG_ALGO_NONE); + + RSession_setActiveKey(rSession, activeKeyId); + + SVPublisher_ASDU asdu1 = SVPublisher_addASDU(svPublisher, "svpub1", NULL, 1); + + int float1 = SVPublisher_ASDU_addFLOAT(asdu1); + int float2 = SVPublisher_ASDU_addFLOAT(asdu1); + int ts1 = SVPublisher_ASDU_addTimestamp(asdu1); + + SVPublisher_ASDU asdu2 = SVPublisher_addASDU(svPublisher, "svpub2", NULL, 1); + + int float3 = SVPublisher_ASDU_addFLOAT(asdu2); + int float4 = SVPublisher_ASDU_addFLOAT(asdu2); + int ts2 = SVPublisher_ASDU_addTimestamp(asdu2); + + SVPublisher_setupComplete(svPublisher); + + float fVal1 = 1234.5678f; + float fVal2 = 0.12345f; + + while (running) { + Timestamp ts; + Timestamp_clearFlags(&ts); + Timestamp_setTimeInMilliseconds(&ts, Hal_getTimeInMs()); + + SVPublisher_ASDU_setFLOAT(asdu1, float1, fVal1); + SVPublisher_ASDU_setFLOAT(asdu1, float2, fVal2); + SVPublisher_ASDU_setTimestamp(asdu1, ts1, ts); + + SVPublisher_ASDU_setFLOAT(asdu2, float3, fVal1 * 2); + SVPublisher_ASDU_setFLOAT(asdu2, float4, fVal2 * 2); + SVPublisher_ASDU_setTimestamp(asdu2, ts2, ts); + + SVPublisher_ASDU_increaseSmpCnt(asdu1); + SVPublisher_ASDU_increaseSmpCnt(asdu2); + + fVal1 += 1.1f; + fVal2 += 0.1f; + + SVPublisher_publish(svPublisher); + + if (Hal_getTimeInMs() >= nextKeyChangeTime) { + /* change key */ + + if (activeKeyId == 1) + activeKeyId = 2; + //else + // activeKeyId = 1; + RSession_removeKey(rSession, 1); + + nextKeyChangeTime = Hal_getTimeInMs() + 5000; + } + + Thread_sleep(50); + } + + SVPublisher_destroy(svPublisher); + } + else { + printf("Failed to create SV publisher\n"); + } + + RSession_destroy(rSession); + } + else { + printf("Failed to create remote session instance\n"); + } + +} diff --git a/examples/rsv_subscriber_example/CMakeLists.txt b/examples/rsv_subscriber_example/CMakeLists.txt new file mode 100644 index 00000000..e1aed14c --- /dev/null +++ b/examples/rsv_subscriber_example/CMakeLists.txt @@ -0,0 +1,30 @@ + +set(r_sv_subscriber_example_SRCS + r_sv_subscriber_example.c +) + +IF(WIN32) + +set_source_files_properties(${r_sv_subscriber_example_SRCS} + PROPERTIES LANGUAGE CXX) +add_executable(r_sv_subscriber_example + ${r_sv_subscriber_example_SRCS} +) + +target_link_libraries(r_sv_subscriber_example + iec61850 +) + +ELSE(WIN32) + +add_executable(r_sv_subscriber_example + ${r_sv_subscriber_example_SRCS} +) + +target_link_libraries(r_sv_subscriber_example + iec61850 +) + +ENDIF(WIN32) + + diff --git a/examples/rsv_subscriber_example/r_sv_subscriber_example.c b/examples/rsv_subscriber_example/r_sv_subscriber_example.c new file mode 100644 index 00000000..7fdc591c --- /dev/null +++ b/examples/rsv_subscriber_example/r_sv_subscriber_example.c @@ -0,0 +1,106 @@ +/* + * r-sv-example.c + */ + + +#include "sv_subscriber.h" +#include +#include +#include "hal_thread.h" + +static bool running = true; + +void sigint_handler(int signalId) +{ + running = 0; +} + +/* Callback handler for received SV messages */ +static void +svUpdateListener (SVSubscriber subscriber, void* parameter, SVSubscriber_ASDU asdu) +{ + printf("Received SV message:\n"); + + const char* svID = SVSubscriber_ASDU_getSvId(asdu); + + if (svID != NULL) + printf(" svID=(%s)\n", svID); + + printf(" smpCnt: %i\n", SVSubscriber_ASDU_getSmpCnt(asdu)); + printf(" confRev: %u\n", SVSubscriber_ASDU_getConfRev(asdu)); + + /* + * Access to the data requires a priori knowledge of the data set. + * For this example we assume a data set consisting of FLOAT32 values. + * A FLOAT32 value is encoded as 4 bytes. You can find the first FLOAT32 + * value at byte position 0, the second value at byte position 4, the third + * value at byte position 8, and so on. + * + * To prevent damages due configuration, please check the length of the + * data block of the SV message before accessing the data. + */ + if (SVSubscriber_ASDU_getDataSize(asdu) >= 8) { + printf(" DATA[0]: %f\n", SVSubscriber_ASDU_getFLOAT32(asdu, 0)); + printf(" DATA[1]: %f\n", SVSubscriber_ASDU_getFLOAT32(asdu, 4)); + } +} + +int +main(int argc, char** argv) +{ + RSession rSession = RSession_create(); + + if (rSession) { + + RSession_setLocalAddress(rSession, "0.0.0.0", 102); + + RSession_addMulticastGroup(rSession, "230.0.10.10"); + + char* key1 = "0123456789ABCDEF"; + char* key2 = "FEDCBA9876543210"; + + RSession_addKey(rSession, 1, (uint8_t*)key1, 16, R_SESSION_SEC_ALGO_AES_128_GCM, R_SESSION_SIG_ALGO_NONE); + RSession_addKey(rSession, 2, (uint8_t*)key2, 16, R_SESSION_SEC_ALGO_AES_128_GCM, R_SESSION_SIG_ALGO_NONE); + + SVReceiver receiver = SVReceiver_createRemote(rSession); + + if (receiver) { + /* Create a subscriber listening to SV messages with APPID 4000h */ + SVSubscriber subscriber = SVSubscriber_create(NULL, 0x4000); + + /* Install a callback handler for the subscriber */ + SVSubscriber_setListener(subscriber, svUpdateListener, NULL); + + /* Connect the subscriber to the receiver */ + SVReceiver_addSubscriber(receiver, subscriber); + + /* Start listening to SV messages - starts a new receiver background thread */ + SVReceiver_start(receiver); + + if (SVReceiver_isRunning(receiver)) { + signal(SIGINT, sigint_handler); + + while (running) + Thread_sleep(1); + + /* Stop listening to SV messages */ + SVReceiver_stop(receiver); + } + else { + printf("Failed to start SV subscriber. Reason can be that the Ethernet interface doesn't exist or root permission are required.\n"); + } + + /* Cleanup and free resources */ + SVReceiver_destroy(receiver); + } + else { + printf("Failed to create SV receiver\n"); + } + + RSession_destroy(rSession); + } + else { + printf("Failed to create remote session protocol\n"); + } + +} diff --git a/examples/sntp_example/CMakeLists.txt b/examples/sntp_example/CMakeLists.txt new file mode 100644 index 00000000..7314d669 --- /dev/null +++ b/examples/sntp_example/CMakeLists.txt @@ -0,0 +1,30 @@ + +set(sntp_example_SRCS + sntp_example.c +) + +IF(WIN32) + +set_source_files_properties(${sntp_example_SRCS} + PROPERTIES LANGUAGE CXX) +add_executable(sntp_example + ${sntp_example_SRCS} +) + +target_link_libraries(sntp_example + iec61850 +) + +ELSE(WIN32) + +add_executable(sntp_example + ${sntp_example_SRCS} +) + +target_link_libraries(sntp_example + iec61850 +) + +ENDIF(WIN32) + + diff --git a/examples/sntp_example/sntp_example.c b/examples/sntp_example/sntp_example.c new file mode 100644 index 00000000..b395a60d --- /dev/null +++ b/examples/sntp_example/sntp_example.c @@ -0,0 +1,49 @@ +/* + * sntp_example.c + */ + +#include "sntp_client.h" +#include "hal_thread.h" +#include +#include + +static bool running = true; + +void +sigint_handler(int signalId) +{ + running = false; +} + +static void +sntpUserCallback(void* parameter, bool isSynced) +{ + if (isSynced) + printf("SNTP: Clock synchronized\n"); + else + printf("SNTP: Clock not synchronized\n"); +} + +int +main(int argc, char** argv) +{ + SNTPClient client = SNTPClient_create(); + + //SNTPClient_addServer(client, "127.0.0.1", 1236); + SNTPClient_addServer(client, "192.168.178.74", 123); + + SNTPClient_setUserCallback(client, sntpUserCallback, NULL); + + SNTPClient_setPollInterval(client, 16); + + SNTPClient_start(client); + + signal(SIGINT, sigint_handler); + + while (running) { + Thread_sleep(100); + } + + SNTPClient_destroy(client); +} +