diff --git a/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs b/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs
index 4b45fe54..16d79a56 100644
--- a/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs
+++ b/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs
@@ -1,7 +1,7 @@
/*
* IEC61850ClientAPI.cs
*
- * Copyright 2014-2021 Michael Zillgith
+ * Copyright 2014-2023 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -437,6 +437,9 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedConnection_connect(IntPtr self, out int error, string hostname, int tcpPort);
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern void IedConnection_setLocalAddress(IntPtr self, string localIpAddress, int localPort);
+
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedConnection_abort(IntPtr self, out int error);
@@ -894,6 +897,25 @@ namespace IEC61850
Connect(hostname, -1);
}
+ ///
+ /// Set the local IP address and port to be used by the client
+ ///
+ /// the local IP address or hostname
+ /// the local TCP port to use. When 0 the OS will chose the TCP port to use.
+ public void SetLocalAddress(string localIpAddress, int localPort)
+ {
+ IedConnection_setLocalAddress(connection, localIpAddress, localPort);
+ }
+
+ ///
+ /// Set the local IP address to be used by the client
+ ///
+ /// the local IP address or hostname
+ public void SetLocalAddress(string localIpAddress)
+ {
+ IedConnection_setLocalAddress(connection, localIpAddress, 0);
+ }
+
/// This exception is thrown if there is a connection or service error
public ControlObject CreateControlObject(string objectReference)
{
diff --git a/examples/iec61850_client_example1/client_example1.c b/examples/iec61850_client_example1/client_example1.c
index f84d37a0..6c9241f0 100644
--- a/examples/iec61850_client_example1/client_example1.c
+++ b/examples/iec61850_client_example1/client_example1.c
@@ -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,19 +45,34 @@ 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) {
-
+ if (value != NULL)
+ {
if (MmsValue_getType(value) == MMS_FLOAT) {
float fval = MmsValue_toFloat(value);
printf("read float value: %f\n", fval);
@@ -137,7 +155,6 @@ close_connection:
}
IedConnection_destroy(con);
+
return 0;
}
-
-
diff --git a/src/iec61850/client/ied_connection.c b/src/iec61850/client/ied_connection.c
index b49a1fe7..bc581dea 100644
--- a/src/iec61850/client/ied_connection.c
+++ b/src/iec61850/client/ied_connection.c
@@ -651,6 +651,15 @@ IedConnection_tick(IedConnection self)
return MmsConnection_tick(self->connection);
}
+void
+IedConnection_setLocalAddress(IedConnection self, const char* localIpAddress, int localPort)
+{
+ MmsConnection connection = self->connection;
+ IsoConnectionParameters isoP = MmsConnection_getIsoConnectionParameters(connection);
+
+ IsoConnectionParameters_setLocalTcpParameters(isoP, localIpAddress, localPort);
+}
+
void
IedConnection_setConnectTimeout(IedConnection self, uint32_t timeoutInMs)
{
diff --git a/src/iec61850/inc/iec61850_client.h b/src/iec61850/inc/iec61850_client.h
index 852f2192..c3a174fe 100644
--- a/src/iec61850/inc/iec61850_client.h
+++ b/src/iec61850/inc/iec61850_client.h
@@ -231,6 +231,17 @@ IedConnection_createWithTlsSupport(TLSConfiguration tlsConfig);
LIB61850_API void
IedConnection_destroy(IedConnection self);
+/**
+* \brief Set the local IP address and port to be used by the client
+*
+* NOTE: This function is optional. When not used the OS decides what IP address and TCP port to use.
+*
+* \param self IedConnection instance
+* \param localIpAddress the local IP address or hostname as C string
+* \param localPort the local TCP port to use. When < 1 the OS will chose the TCP port to use.
+*/
+LIB61850_API void
+IedConnection_setLocalAddress(IedConnection self, const char* localIpAddress, int localPort);
/**
* \brief set the connect timeout in ms
diff --git a/src/mms/inc/iso_connection_parameters.h b/src/mms/inc/iso_connection_parameters.h
index cdd04bcb..3514f437 100644
--- a/src/mms/inc/iso_connection_parameters.h
+++ b/src/mms/inc/iso_connection_parameters.h
@@ -145,6 +145,9 @@ struct sIsoConnectionParameters
const char* hostname;
int tcpPort;
+ const char* localIpAddress;
+ int localTcpPort;
+
uint8_t remoteApTitle[10];
int remoteApTitleLen;
int remoteAEQualifier;
@@ -215,6 +218,20 @@ IsoConnectionParameters_setAcseAuthenticationParameter(IsoConnectionParameters s
LIB61850_API void
IsoConnectionParameters_setTcpParameters(IsoConnectionParameters self, const char* hostname, int tcpPort);
+/**
+* \brief Set Local TCP parameters (FOR LIBRARY INTERNAL USE)
+*
+* NOTE: This function used internally by the MMS Client library. When using the MMS or IEC 61850 API
+* there should be no reason for the user to call this function
+*
+* \param self the IsoConnectionParameters instance
+* \param localIpAddress the hostname of local IP address of the server
+* \param localTcpPort the local TCP port number of the server
+*/
+LIB61850_API void
+IsoConnectionParameters_setLocalTcpParameters(IsoConnectionParameters self, const char* localIpAddress, int localTcpPort);
+
+
/**
* \brief set the remote AP-Title and AE-Qualifier
*
diff --git a/src/mms/iso_client/iso_client_connection.c b/src/mms/iso_client/iso_client_connection.c
index cb58e98f..4f37176b 100644
--- a/src/mms/iso_client/iso_client_connection.c
+++ b/src/mms/iso_client/iso_client_connection.c
@@ -692,8 +692,13 @@ IsoClientConnection_associateAsync(IsoClientConnection self, uint32_t connectTim
/* set timeout for connect */
self->nextReadTimeout = Hal_getTimeInMs() + connectTimeoutInMs;
+ /* Connect to Local Ip Address*/
+ if (self->parameters->localIpAddress) {
+ Socket_bind(self->socket, self->parameters->localIpAddress, self->parameters->localTcpPort);
+ }
+
if (Socket_connectAsync(self->socket, self->parameters->hostname, self->parameters->tcpPort) == false) {
-
+
Socket_destroy(self->socket);
self->socket = NULL;
@@ -704,9 +709,9 @@ IsoClientConnection_associateAsync(IsoClientConnection self, uint32_t connectTim
success = false;
}
-
+
Semaphore_post(self->tickMutex);
-
+
return success;
}
diff --git a/src/mms/iso_common/iso_connection_parameters.c b/src/mms/iso_common/iso_connection_parameters.c
index 3fdf32c9..aa5334b3 100644
--- a/src/mms/iso_common/iso_connection_parameters.c
+++ b/src/mms/iso_common/iso_connection_parameters.c
@@ -104,6 +104,18 @@ IsoConnectionParameters_setTcpParameters(IsoConnectionParameters self, const cha
self->tcpPort = tcpPort;
}
+void
+IsoConnectionParameters_setLocalTcpParameters(IsoConnectionParameters self, const char* localIpAddress, int localTcpPort)
+{
+ if (self) {
+ if (localIpAddress) {
+ self->localIpAddress = strdup(localIpAddress);
+ self->localTcpPort = localTcpPort;
+ }
+ }
+}
+
+
void
IsoConnectionParameters_setRemoteApTitle(IsoConnectionParameters self, const char* apTitle, int aeQualifier)
{