UpdateBuilder seems do not send timestamp in local time

155 views
Skip to first unread message

Matteo Chiappa

unread,
Jul 5, 2020, 10:19:40 PM7/5/20
to opendnp3
Hello,
I'm using opendnp3 release 3.x to implement an outstation in C/C++.
During general interrogation requested by the master, objects sent by the outstation have timestamp properly set to local time.

I have difficult to send unsolicited variation to the master with timestamp in local time.
I verified that local timestamp has correct offest respect to UTC.

Here is a code snip:

Analog myAn;
case ((int)GroupVariation::Group32Var7):
    DNPTimeStamp = DNPTime(GetTimeStampMilliseconds(true), TimestampQuality::SYNCHRONIZED);
    dValue = (double)iRegValueToUpdate;
    AnalogQualityFlag.Set(AnalogQuality::ONLINE);
    myAn = Analog(dValue, AnalogQualityFlag, DNPTimeStamp);
    builder.Update(myAn, pDnp3->Addr, EventMode::Detect);
    pGw->outstation->Apply(builder.Build());
    break;

I'm not able to identify the error.
Any help is appreciated.

Matteo Chiappa



Andrea Chiappa

unread,
Jul 6, 2020, 3:52:49 PM7/6/20
to opendnp3
Hello Adam,
any suggestion for issue below?

Matteo

Adam Crain

unread,
Jul 6, 2020, 4:09:58 PM7/6/20
to opendnp3
DNP3 timestamps should be UTC per the standard. That said, if your outstation and master both agree to use local time it will work.

On the wire, DNP3 time is a 48-bit count of milliseconds since Jan 1 @ 00:00:00 (typically UTC).

To provide guidance as to why you're not seeing correct timestamps, we need to see what is being sent on the wire for both scenarios. Not every
DNP3 variation carries a timestamp.  Also, we don't know what your GetTimeStampMillisecond(..) function does.

Try capturing a communication log using Wireshark.

Andrea Chiappa

unread,
Jul 10, 2020, 2:57:04 PM7/10/20
to opendnp3
Hello Adam,
sorry to be back on this issue so late.
Following your suggestion I have been monitor master-outstation communications with tcpdump.
This tell me effectivelly that all objects sent by my outstation are tagged with UTC timestamp
(when timestamp is transported by the corresponding object),
regardless if these are in response to a request from master, or sent as UNSOLICITED RESPONSE by the outstaion.
So, there is something that master simulator that I'm using, is doing to show local date/time.

Now, the next step was to understand why even using GetTimeStampMilliseconds(true) it was not showing timestamp
in local time.
Hereafter is what GetTimeStampMillisecond is doing:

uint64_t GetTimeStampMilliseconds (bool bLocalTime)
{

  time_t rawtime;
  timeval curTime;
  uint64_t retval;
  struct tm * pTimeinfo;
  struct tm timeinfo;

  time (&rawtime);
  pTimeinfo = localtime (&rawtime);
  timeinfo = *pTimeinfo;
  gettimeofday(&curTime, NULL);
  retval = (((uint64_t)(curTime.tv_sec)) * 1000) + (((uint64_t)(curTime.tv_usec)) / 1000);

  if (bLocalTime == true) {
    retval = retval + timeinfo.tm_gmtoff;  ----> BUG
  }

  return retval;

}

As you can see, there was a bug. The correct handling of tm_gmtoff is
retval = retval + (timeinfo.tm_gmtoff * 1000);   //* 1000 is to convert tm_gmtoff in milliseconds

After correction, I'm now able to use timestamp in UTC or localtime, based on configuration.

Thanks a lot to everyone for the support.

Andrea Chiappa
Reply all
Reply to author
Forward
0 new messages