|
|
|
@ -1,5 +1,5 @@
|
|
|
|
|
/*
|
|
|
|
|
* tls_client_example.c
|
|
|
|
|
* tls_client_exmaple.c
|
|
|
|
|
*
|
|
|
|
|
* This example shows how to configure TLS
|
|
|
|
|
*/
|
|
|
|
@ -12,58 +12,35 @@
|
|
|
|
|
#include "hal_thread.h"
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
printSpaces(int spaces)
|
|
|
|
|
reportCallbackFunction(void* parameter, ClientReport report)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < spaces; i++)
|
|
|
|
|
printf(" ");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
printDataDirectory(char* doRef, IedConnection con, int spaces)
|
|
|
|
|
{
|
|
|
|
|
IedClientError error;
|
|
|
|
|
|
|
|
|
|
LinkedList dataAttributes = IedConnection_getDataDirectory(con, &error, doRef);
|
|
|
|
|
|
|
|
|
|
//LinkedList dataAttributes = IedConnection_getDataDirectoryByFC(con, &error, doRef, MX);
|
|
|
|
|
|
|
|
|
|
if (dataAttributes != NULL) {
|
|
|
|
|
LinkedList dataAttribute = LinkedList_getNext(dataAttributes);
|
|
|
|
|
|
|
|
|
|
while (dataAttribute != NULL) {
|
|
|
|
|
char* daName = (char*) dataAttribute->data;
|
|
|
|
|
MmsValue* dataSetValues = ClientReport_getDataSetValues(report);
|
|
|
|
|
|
|
|
|
|
printSpaces(spaces);
|
|
|
|
|
printf("DA: %s\n", (char*) dataAttribute->data);
|
|
|
|
|
printf("received report for %s\n", ClientReport_getRcbReference(report));
|
|
|
|
|
|
|
|
|
|
dataAttribute = LinkedList_getNext(dataAttribute);
|
|
|
|
|
int i;
|
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
|
ReasonForInclusion reason = ClientReport_getReasonForInclusion(report, i);
|
|
|
|
|
|
|
|
|
|
char daRef[130];
|
|
|
|
|
sprintf(daRef, "%s.%s", doRef, daName);
|
|
|
|
|
printDataDirectory(daRef, con, spaces + 2);
|
|
|
|
|
if (reason != IEC61850_REASON_NOT_INCLUDED) {
|
|
|
|
|
printf(" GGIO1.SPCSO%i.stVal: %i (included for reason %i)\n", i,
|
|
|
|
|
MmsValue_getBoolean(MmsValue_getElement(dataSetValues, i)), reason);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LinkedList_destroy(dataAttributes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
main(int argc, char** argv)
|
|
|
|
|
{
|
|
|
|
|
int main(int argc, char** argv) {
|
|
|
|
|
|
|
|
|
|
char* hostname;
|
|
|
|
|
int tcpPort = 8102;
|
|
|
|
|
int port_number = -1;
|
|
|
|
|
|
|
|
|
|
if (argc > 1)
|
|
|
|
|
if (argc > 2) {
|
|
|
|
|
hostname = argv[1];
|
|
|
|
|
port_number = atoi(argv[2]);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
hostname = "localhost";
|
|
|
|
|
|
|
|
|
|
if (argc > 2)
|
|
|
|
|
tcpPort = atoi(argv[2]);
|
|
|
|
|
|
|
|
|
|
TLSConfiguration tlsConfig = TLSConfiguration_create();
|
|
|
|
|
|
|
|
|
|
TLSConfiguration_setChainValidation(tlsConfig, true);
|
|
|
|
@ -84,147 +61,102 @@ main(int argc, char** argv)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
IedClientError error;
|
|
|
|
|
|
|
|
|
|
IedConnection con = IedConnection_createWithTlsSupport(tlsConfig);
|
|
|
|
|
|
|
|
|
|
IedConnection_connect(con, &error, hostname, tcpPort);
|
|
|
|
|
IedConnection_connect(con, &error, hostname, port_number);
|
|
|
|
|
|
|
|
|
|
if (error == IED_ERROR_OK) {
|
|
|
|
|
|
|
|
|
|
printf("Get logical device list...\n");
|
|
|
|
|
LinkedList deviceList = IedConnection_getLogicalDeviceList(con, &error);
|
|
|
|
|
|
|
|
|
|
if (error != IED_ERROR_OK) {
|
|
|
|
|
printf("Failed to read device list (error code: %i)\n", error);
|
|
|
|
|
goto cleanup_and_exit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LinkedList device = LinkedList_getNext(deviceList);
|
|
|
|
|
|
|
|
|
|
while (device != NULL) {
|
|
|
|
|
printf("LD: %s\n", (char*) device->data);
|
|
|
|
|
LinkedList serverDirectory = IedConnection_getServerDirectory(con, &error, false);
|
|
|
|
|
|
|
|
|
|
LinkedList logicalNodes = IedConnection_getLogicalDeviceDirectory(con, &error,
|
|
|
|
|
(char*) device->data);
|
|
|
|
|
if (error != IED_ERROR_OK)
|
|
|
|
|
printf("failed to read server directory (error=%i)\n", error);
|
|
|
|
|
|
|
|
|
|
LinkedList logicalNode = LinkedList_getNext(logicalNodes);
|
|
|
|
|
if (serverDirectory)
|
|
|
|
|
LinkedList_destroy(serverDirectory);
|
|
|
|
|
|
|
|
|
|
while (logicalNode != NULL) {
|
|
|
|
|
printf(" LN: %s\n", (char*) logicalNode->data);
|
|
|
|
|
/* read an analog measurement value from server */
|
|
|
|
|
MmsValue* value = IedConnection_readObject(con, &error, "simpleIOGenericIO/GGIO1.AnIn1.mag.f", IEC61850_FC_MX);
|
|
|
|
|
|
|
|
|
|
char lnRef[129];
|
|
|
|
|
|
|
|
|
|
sprintf(lnRef, "%s/%s", (char*) device->data, (char*) logicalNode->data);
|
|
|
|
|
|
|
|
|
|
LinkedList dataObjects = IedConnection_getLogicalNodeDirectory(con, &error,
|
|
|
|
|
lnRef, ACSI_CLASS_DATA_OBJECT);
|
|
|
|
|
|
|
|
|
|
LinkedList dataObject = LinkedList_getNext(dataObjects);
|
|
|
|
|
|
|
|
|
|
while (dataObject != NULL) {
|
|
|
|
|
char* dataObjectName = (char*) dataObject->data;
|
|
|
|
|
|
|
|
|
|
printf(" DO: %s\n", dataObjectName);
|
|
|
|
|
|
|
|
|
|
dataObject = LinkedList_getNext(dataObject);
|
|
|
|
|
|
|
|
|
|
char doRef[129];
|
|
|
|
|
|
|
|
|
|
sprintf(doRef, "%s/%s.%s", (char*) device->data, (char*) logicalNode->data, dataObjectName);
|
|
|
|
|
|
|
|
|
|
printDataDirectory(doRef, con, 6);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LinkedList_destroy(dataObjects);
|
|
|
|
|
|
|
|
|
|
LinkedList dataSets = IedConnection_getLogicalNodeDirectory(con, &error, lnRef,
|
|
|
|
|
ACSI_CLASS_DATA_SET);
|
|
|
|
|
|
|
|
|
|
LinkedList dataSet = LinkedList_getNext(dataSets);
|
|
|
|
|
|
|
|
|
|
while (dataSet != NULL) {
|
|
|
|
|
char* dataSetName = (char*) dataSet->data;
|
|
|
|
|
bool isDeletable;
|
|
|
|
|
char dataSetRef[130];
|
|
|
|
|
sprintf(dataSetRef, "%s.%s", lnRef, dataSetName);
|
|
|
|
|
|
|
|
|
|
LinkedList dataSetMembers = IedConnection_getDataSetDirectory(con, &error, dataSetRef,
|
|
|
|
|
&isDeletable);
|
|
|
|
|
|
|
|
|
|
if (isDeletable)
|
|
|
|
|
printf(" Data set: %s (deletable)\n", dataSetName);
|
|
|
|
|
else
|
|
|
|
|
printf(" Data set: %s (not deletable)\n", dataSetName);
|
|
|
|
|
|
|
|
|
|
LinkedList dataSetMemberRef = LinkedList_getNext(dataSetMembers);
|
|
|
|
|
|
|
|
|
|
while (dataSetMemberRef != NULL) {
|
|
|
|
|
if (value != NULL) {
|
|
|
|
|
float fval = MmsValue_toFloat(value);
|
|
|
|
|
printf("read float value: %f\n", fval);
|
|
|
|
|
MmsValue_delete(value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char* memberRef = (char*) dataSetMemberRef->data;
|
|
|
|
|
/* write a variable to the server */
|
|
|
|
|
value = MmsValue_newVisibleString("libiec61850.com");
|
|
|
|
|
IedConnection_writeObject(con, &error, "simpleIOGenericIO/GGIO1.NamPlt.vendor", IEC61850_FC_DC, value);
|
|
|
|
|
|
|
|
|
|
printf(" %s\n", memberRef);
|
|
|
|
|
if (error != IED_ERROR_OK)
|
|
|
|
|
printf("failed to write simpleIOGenericIO/GGIO1.NamPlt.vendor!\n");
|
|
|
|
|
|
|
|
|
|
dataSetMemberRef = LinkedList_getNext(dataSetMemberRef);
|
|
|
|
|
}
|
|
|
|
|
MmsValue_delete(value);
|
|
|
|
|
|
|
|
|
|
LinkedList_destroy(dataSetMembers);
|
|
|
|
|
|
|
|
|
|
dataSet = LinkedList_getNext(dataSet);
|
|
|
|
|
}
|
|
|
|
|
/* read data set */
|
|
|
|
|
ClientDataSet clientDataSet = IedConnection_readDataSetValues(con, &error, "simpleIOGenericIO/LLN0.Events", NULL);
|
|
|
|
|
|
|
|
|
|
LinkedList_destroy(dataSets);
|
|
|
|
|
if (clientDataSet == NULL)
|
|
|
|
|
printf("failed to read dataset\n");
|
|
|
|
|
|
|
|
|
|
LinkedList reports = IedConnection_getLogicalNodeDirectory(con, &error, lnRef,
|
|
|
|
|
ACSI_CLASS_URCB);
|
|
|
|
|
/* Read RCB values */
|
|
|
|
|
ClientReportControlBlock rcb =
|
|
|
|
|
IedConnection_getRCBValues(con, &error, "simpleIOGenericIO/LLN0.RP.EventsRCB01", NULL);
|
|
|
|
|
|
|
|
|
|
LinkedList report = LinkedList_getNext(reports);
|
|
|
|
|
|
|
|
|
|
while (report != NULL) {
|
|
|
|
|
char* reportName = (char*) report->data;
|
|
|
|
|
bool rptEna = ClientReportControlBlock_getRptEna(rcb);
|
|
|
|
|
|
|
|
|
|
printf(" RP: %s\n", reportName);
|
|
|
|
|
printf("RptEna = %i\n", rptEna);
|
|
|
|
|
|
|
|
|
|
report = LinkedList_getNext(report);
|
|
|
|
|
}
|
|
|
|
|
/* Install handler for reports */
|
|
|
|
|
IedConnection_installReportHandler(con, "simpleIOGenericIO/LLN0.RP.EventsRCB01",
|
|
|
|
|
ClientReportControlBlock_getRptId(rcb), reportCallbackFunction, NULL);
|
|
|
|
|
|
|
|
|
|
LinkedList_destroy(reports);
|
|
|
|
|
/* 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);
|
|
|
|
|
|
|
|
|
|
reports = IedConnection_getLogicalNodeDirectory(con, &error, lnRef,
|
|
|
|
|
ACSI_CLASS_BRCB);
|
|
|
|
|
if (error != IED_ERROR_OK)
|
|
|
|
|
printf("report activation failed (code: %i)\n", error);
|
|
|
|
|
|
|
|
|
|
report = LinkedList_getNext(reports);
|
|
|
|
|
Thread_sleep(1000);
|
|
|
|
|
|
|
|
|
|
while (report != NULL) {
|
|
|
|
|
char* reportName = (char*) report->data;
|
|
|
|
|
/* trigger GI report */
|
|
|
|
|
ClientReportControlBlock_setGI(rcb, true);
|
|
|
|
|
IedConnection_setRCBValues(con, &error, rcb, RCB_ELEMENT_GI, true);
|
|
|
|
|
|
|
|
|
|
printf(" BR: %s\n", reportName);
|
|
|
|
|
if (error != IED_ERROR_OK)
|
|
|
|
|
printf("Error triggering a GI report (code: %i)\n", error);
|
|
|
|
|
|
|
|
|
|
report = LinkedList_getNext(report);
|
|
|
|
|
}
|
|
|
|
|
Thread_sleep(60000);
|
|
|
|
|
|
|
|
|
|
LinkedList_destroy(reports);
|
|
|
|
|
/* disable reporting */
|
|
|
|
|
ClientReportControlBlock_setRptEna(rcb, false);
|
|
|
|
|
IedConnection_setRCBValues(con, &error, rcb, RCB_ELEMENT_RPT_ENA, true);
|
|
|
|
|
|
|
|
|
|
logicalNode = LinkedList_getNext(logicalNode);
|
|
|
|
|
}
|
|
|
|
|
if (error != IED_ERROR_OK)
|
|
|
|
|
printf("disable reporting failed (code: %i)\n", error);
|
|
|
|
|
|
|
|
|
|
LinkedList_destroy(logicalNodes);
|
|
|
|
|
ClientDataSet_destroy(clientDataSet);
|
|
|
|
|
|
|
|
|
|
device = LinkedList_getNext(device);
|
|
|
|
|
}
|
|
|
|
|
ClientReportControlBlock_destroy(rcb);
|
|
|
|
|
|
|
|
|
|
LinkedList_destroy(deviceList);
|
|
|
|
|
close_connection:
|
|
|
|
|
|
|
|
|
|
IedConnection_close(con);
|
|
|
|
|
TLSConfiguration_destroy(tlsConfig);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
printf("Connection failed!\n");
|
|
|
|
|
printf("Failed to connect to %s\n", hostname);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cleanup_and_exit:
|
|
|
|
|
IedConnection_destroy(con);
|
|
|
|
|
|
|
|
|
|
TLSConfiguration_destroy(tlsConfig);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|