Monday, May 13, 2019

Time on MQTT

I've been promising for a while to write about the time keeping on the network. Well, now is a good time.

Time can be important for many applications. Automatically enabling an alarm system is one use, setback thermostats are another use. One thing that everyone wants to know is what time is it now. The answer to what time is it now, ought to be the same for all systems on the network.

The Raspberry PI has an on-board clock that keeps pretty good time. It adjusts local time for daylight savings and other similar events.

Node red can query the server time, and use that for various things. For my setup, I have a global context to hold the current hours and minutes, and I have an mqtt message sent out every second with the full local time details in a JSON payload.


I mostly only worry about local time, so that the nodes don't have to convert to local time. The individual elements allow the various nodes to act when the hour is 3 or when the minute is 33. They can use any combinations of the current time.

The flow is very simple:


The convert time function converts the system time to local (central) time. Toward the top, where the "new Date()" call is made, there is a language format (en-US, english United States), ant the timezone is "America/Chicago" which is US central time.

// Create a new JavaScript Date object based on the timestamp
// multiplied by 1000 so that the argument is in milliseconds, not seconds.

var currentUtcTime = new Date(); // This is in UTC
var date = new Date(currentUtcTime.toLocaleString('en-US', { timeZone: 'America/Chicago' }));

// Hours part from the timestamp
var hours = "0" + date.getHours();
// Minutes part from the timestamp
var minutes = "0" + date.getMinutes();
// Seconds part from the timestamp
var seconds = "0" + date.getSeconds();

var year = date.getYear()+1900;
var month = "0"+(date.getMonth()+1);
var day = "0"+date.getDate();
// Will display time in 21:30:23 format

var timeStr = year+"-"+month.substr(-2)+"-"+day.substr(-2)+"T"+
              hours.substr(-2) + ':' + minutes.substr(-2) + ':' + seconds.substr(-2);

context.global.hour = date.getHours();
context.global.minute = date.getMinutes();

msg.payload = {"CDTstring" : timeStr,
               "hour": date.getHours(),
               "minute": date.getMinutes(),
               "second": date.getSeconds(),
               "year": date.getYear()+1900,
               "month": date.getMonth()+1,
               "day" : date.getDate()};


return msg;

The timestamp is the inject node firing once a second.



I use the topic "time/ISO-8601" because I was outputting that only for the time. The UTC conversion was done on the nodes, but I quickly found that to be tedious to do for each node that needed the time. Now I do the conversion in node-red and send out the converted time.

Now maybe the other nodes that use time will be more complete.

Should I write about GPIO next time, or USB connected Arduino's? Both are supported by node-red, and can have use in an automated system. Let me know.


No comments:

Post a Comment