Learn open62541 --- [32] Obtain system time correctly

When the client communicates with the server, it sometimes asks for the system time of the server, for example, to view the specific time when an event occurred.

In the previous series of articles, we have always used UA_DateTime_now() to obtain the system time. The time obtained by this API is UTC time, which is the universal coordinated time. We are in China and the specific time is:

The time difference between the time in Mainland China, Hong Kong, Macau, Taiwan, Mongolia, Singapore, Malaysia, Philippines, Western Australia and UTC is all +8, which is UTC+8.

PS: This 8 refers to 8 hours

Let us first look at the printing performance of UTC time and how to get the correct system time.


A phenomenon

Below is the server.c code,

#include "open62541.h"

#include <signal.h>
#include <stdlib.h>

UA_Boolean running = true;

static void stopHandler(int sign) {
    
    
	UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "received ctrl-c");
	running = false;
}

static void cycleCallback(UA_Server *server, void *data)
{
    
    
	UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "ctrl callback");


	UA_DateTimeStruct dts = UA_DateTime_toStruct(UA_DateTime_now());

	UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "date is: %u-%u-%u %u:%u:%u.%03u\n",
		dts.year, dts.month, dts.day, dts.hour, dts.min, dts.sec, dts.milliSec);
}



int main(void)
{
    
    
	signal(SIGINT, stopHandler);
	signal(SIGTERM, stopHandler);

	UA_Server *server = UA_Server_new();
	UA_ServerConfig_setDefault(UA_Server_getConfig(server));


	UA_Server_addRepeatedCallback(server, cycleCallback, NULL, 2000, NULL); // call every 2s

	UA_StatusCode retval = UA_Server_run(server, &running);

	UA_Server_delete(server);

	return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;
}

In the code, the function cycleCallback() will be called every 2s. The function will print the time obtained by UA_DateTime_now(). The final print is as follows. The
Insert picture description here
left side is the time taken out when the log is printed by the function UA_LOG_INFO(). This time is the same as the real system. The time is the same. The time printed on the right is the time obtained by UA_DateTime_now(). You can see that the difference is 8 hours.


Second, get the correct system time

open62541 provides an API to calculate the offset of the server's time zone relative to UTC, namely UA_DateTime_localTimeUtcOffset()

Let's re-adjust cycleCallback() to the following,

static void ctrlCallback(UA_Server *server, void *data)
{
    
    
	UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "ctrl callback");


	UA_Int64 tOffset = UA_DateTime_localTimeUtcOffset();
	
	// 打印这个偏移值
	UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "offset: %lld", tOffset);
	
	// UA_DateTime_now()加上偏移值,得到正确的系统时间
	UA_DateTimeStruct dts = UA_DateTime_toStruct(UA_DateTime_now() + tOffset);
	

	UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "date is: %u-%u-%u %u:%u:%u.%03u\n",
		dts.year, dts.month, dts.day, dts.hour, dts.min, dts.sec, dts.milliSec);
}

If you print the following,
Insert picture description here
you can see that the correct time is now obtained. You can compare it with the time on your computer, and it is also consistent.

The offset value printed out is 288000000000, why is this value? As mentioned earlier, China’s time zone is UTC+8, which means that the offset is 8 hours, and 8 hours is converted to seconds 8 x 60 x 60 = 28800. The smallest unit for calculating the time in open62541 is 1/10 microseconds , so multiply it by 10000000. Get 288000000000


Three summary

This article mainly describes how to obtain the correct system time and the principles behind it, mainly related to the specific time zone.

If there is something wrong with the writing, I hope to leave a message to correct it, thank you for reading.

Guess you like

Origin blog.csdn.net/whahu1989/article/details/106729909