My AMR sample program is reading data from the meter continuously in one thread. I want run to check connection status in another thread. But how will client (AMR application) get disconnection status from the meter? Is any call back function there?
If AMR application get disconnection status, then it could try to reconnect to the meter.
Kindly suggest me what should I do to get disconnection status?
Meter doesn't notify when a connection is closed. You can check is TCP/IP connection up or poll the meter, but don't do it on the other thread. It'll cause problems.
Check if the connection is inactive and try to read some data from the meter example every 30 second.
There is an inactivity timeout and meter closes the connection if you don't read anything from the meter for a while.
I have implemented two threads in my application. One for connection and another for reading. In this implementation only one thread run at a time. If application is connected to the meter, then connection thread will close and reading thread will run and vice versa.
I am facing problem in this implementation that some time it works properly and some time not.
Problem-1:
Whenever I remove the Ethernet cable from meter port then, the connection thread is running and try to connects. Some time it connects properly and some time the function comm.InitializeConnection() fail and returning error number "258".
Problem-2:
Whenever I remove the Ethernet cable from meter port then, the connection thread is running and try to connects. Some time it connects properly but sometime the reading thread does not release and stuck somewhere. So my connection thread does not run.
Both threads are mentioned below.
/*********************************** Connection thread *************************************/
void connetionThread()
{
int ret=0;
while(!isConnected)
{
TRACE("Trying to connect......................................%d\r\n", 0);
if ((ret = comm.Connect("192.168.0.05", 4059)) != 0){
TRACE("Couldn't connect to the device... %s.\r\n", CGXDLMSConverter::GetErrorMessage(ret));
}else{
TRACE("Connected to the device %s.\r\n", CGXDLMSConverter::GetErrorMessage(ret));
if ((ret = comm.InitializeConnection()) != 0){
comm.Close();
TRACE("Connection initialization failed %s.\r\n", CGXDLMSConverter::GetErrorMessage(ret));
}else{
TRACE("Connection initialization succeeded %s.\r\n", CGXDLMSConverter::GetErrorMessage(ret));
isConnected = true;
}
}
Sleep(2000);
}
}
/*********************************** Reading thread *************************************/
void readingThread()
{
int ret=0;
CGXDLMSClock *objClock = new CGXDLMSClock("0.0.1.0.0.255");
std::string sValues;
while(isConnected)
{
TRACE("Reading device data ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %d\r\n", 0);
But my application has two threads one for connection and another for reading data from the meter.
Because if meter get disconnect, the thread will be active and try to connect meter at same time reading thread will be deactivate.
I have implemented same as suggested by you. It is working properly first time. Whenever I remove Ethernet cable from the meter,
then it is still stuck in the read() function. Actually the comm.read() function is not releasing that's why it is not trying to reconnect the meter.
I have attached application code and its output screen shot.
It is working as suggested by you.
But I am facing one more issue that whenever i remove the Ethernet cable from the meter, then it goes in re-connection loop and trying to reconnect till now it get connected.
Sometime the above scenario is work properly and some time faces re-connection error of "AARQRequest failed 258". It means the function "comm.InitializeConnection()" is not succeeded. In this situation I have to re-start the meter, then it get connected and read the data from the meter.
I have attached screen-shot for the same.
Kindly check and suggest.
If you have established the connection to the meter and connection broke you need to wait until inactivity timeout has elapsed before trying the next connection. You can check what is inactivity timeout from the "IEC HDLC Setup" object.
Hi Pradson,
Hi Pradson,
Meter doesn't notify when a connection is closed. You can check is TCP/IP connection up or poll the meter, but don't do it on the other thread. It'll cause problems.
Check if the connection is inactive and try to read some data from the meter example every 30 second.
There is an inactivity timeout and meter closes the connection if you don't read anything from the meter for a while.
BR,
Mikko
Hi Mikko,
Hi Mikko,
Thanks a lot for your prompt response.
Thanks & Regards,
Pradson
Hi Mikko,
Hi Mikko,
I have implemented two threads in my application. One for connection and another for reading. In this implementation only one thread run at a time. If application is connected to the meter, then connection thread will close and reading thread will run and vice versa.
I am facing problem in this implementation that some time it works properly and some time not.
Problem-1:
Whenever I remove the Ethernet cable from meter port then, the connection thread is running and try to connects. Some time it connects properly and some time the function comm.InitializeConnection() fail and returning error number "258".
Problem-2:
Whenever I remove the Ethernet cable from meter port then, the connection thread is running and try to connects. Some time it connects properly but sometime the reading thread does not release and stuck somewhere. So my connection thread does not run.
Both threads are mentioned below.
/*********************************** Connection thread *************************************/
void connetionThread()
{
int ret=0;
while(!isConnected)
{
TRACE("Trying to connect......................................%d\r\n", 0);
if ((ret = comm.Connect("192.168.0.05", 4059)) != 0){
TRACE("Couldn't connect to the device... %s.\r\n", CGXDLMSConverter::GetErrorMessage(ret));
}else{
TRACE("Connected to the device %s.\r\n", CGXDLMSConverter::GetErrorMessage(ret));
if ((ret = comm.InitializeConnection()) != 0){
comm.Close();
TRACE("Connection initialization failed %s.\r\n", CGXDLMSConverter::GetErrorMessage(ret));
}else{
TRACE("Connection initialization succeeded %s.\r\n", CGXDLMSConverter::GetErrorMessage(ret));
isConnected = true;
}
}
Sleep(2000);
}
}
/*********************************** Reading thread *************************************/
void readingThread()
{
int ret=0;
CGXDLMSClock *objClock = new CGXDLMSClock("0.0.1.0.0.255");
std::string sValues;
while(isConnected)
{
TRACE("Reading device data ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %d\r\n", 0);
sValues.clear();
if ((ret = comm.Read(objClock, 2, sValues)) != 0)
{
comm.Close();
isConnected = false;
TRACE("err! failed to read clock object register: %s \n", CGXDLMSConverter::GetErrorMessage(ret));
m_connectionThread = std::thread(connetionThread);
if(m_connectionThread.joinable()){
m_connectionThread.join();
}
}else{
TRACE("sValues: %s\n", (char*)sValues.c_str());
}
Sleep(5000);
}
}
Kindly suggest me.
Thanks & Regards,
Pradson
Hi,
Hi,
Use only one thread. At the begin, it will start the connection and in loop read values.
There is no need for two threads.
BR,
Mikko
Hi Mikko,
Hi Mikko,
Thanks for reply.
But my application has two threads one for connection and another for reading data from the meter.
Because if meter get disconnect, the thread will be active and try to connect meter at same time reading thread will be deactivate.
So,
How will I apply this logic?
Kindly suggest me.
Regards,
Pradson.
Hi Pradson,
Hi Pradson,
Use one thread and two while loop.
while(true)
{
//Make connection.
while(connection.isUp)
{
//Read values.
}
}
BR,
Mikko
Hi Mikko,
Hi Mikko,
Thanks for reply.
I have implemented same as suggested by you. It is working properly first time. Whenever I remove Ethernet cable from the meter,
then it is still stuck in the read() function. Actually the comm.read() function is not releasing that's why it is not trying to reconnect the meter.
I have attached application code and its output screen shot.
Kindly suggest me what should i do.
Thanks & Regards,
Pradson
Kindly find the screen-shot
Kindly find the screen-shot of "communication.cpp" file and its function "ReadDLMSPacket()". I have mark where it is stuck.
Thanks,
Pradson
Hi,
Hi,
Example is using default timeout.
You can change it setting this after you create the socket.
// WINDOWS
//Timeout in seconds.
DWORD to = timeout * 1000;
setsockopt(m_socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&to, sizeof to);
// LINUX
struct timeval tv;
tv.tv_sec = //Timeout in seconds.;
tv.tv_usec = 0;
setsockopt(m_socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
BR,
Mikko
Hi Mikko,
Hi Mikko,
Thanks for reply.
It is working as suggested by you.
But I am facing one more issue that whenever i remove the Ethernet cable from the meter, then it goes in re-connection loop and trying to reconnect till now it get connected.
Sometime the above scenario is work properly and some time faces re-connection error of "AARQRequest failed 258". It means the function "comm.InitializeConnection()" is not succeeded. In this situation I have to re-start the meter, then it get connected and read the data from the meter.
I have attached screen-shot for the same.
Kindly check and suggest.
Thanks & Regards,
Pradson
Hi,
Hi,
If you have established the connection to the meter and connection broke you need to wait until inactivity timeout has elapsed before trying the next connection. You can check what is inactivity timeout from the "IEC HDLC Setup" object.
BR,
Mikko
Thanks a lot Mikko.
Thanks a lot Mikko.
Now it is working fine.
All issues have been resolved.
Thanks & Regards,
Pradson