Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of M2XStreamClient by
TimeService.cpp
- Committer:
- citrusbyte
- Date:
- 2015-12-28
- Revision:
- 16:7903152de19f
File content as of revision 16:7903152de19f:
#include "M2XStreamClient.h"
static int fill_iso8601_timestamp(int32_t seconds, int32_t milli,
char* buffer, int* length);
TimeService::TimeService(M2XStreamClient* client) : _client(client) {
}
int TimeService::init() {
_timer.start();
return reset();
}
int TimeService::reset() {
int32_t ts;
int status = _client->getTimestamp32(&ts);
if (m2x_status_is_success(status)) {
_server_timestamp = ts;
_local_last_milli = _timer.read_ms();
}
return status;
}
int TimeService::getTimestamp(char* buffer, int* length) {
uint32_t now = _timer.read_ms();
if (now < _local_last_milli) {
// In case of a timestamp overflow(happens once every 50 days on
// Arduino), we reset the server timestamp recorded.
int status = reset();
if (!m2x_status_is_success(status)) { return status; }
now = _timer.read_ms();
}
if (now < _local_last_milli) {
// We have already reseted the timestamp, so this cannot happen
// (an HTTP request can take longer than 50 days to finished? You
// must be kidding here). Something else must be wrong here
return E_TIMESTAMP_ERROR;
}
uint32_t diff = now - _local_last_milli;
_local_last_milli = now;
_server_timestamp += (int32_t) (diff / 1000); // Milliseconds to seconds
return fill_iso8601_timestamp(_server_timestamp, (int32_t) (diff % 1000),
buffer, length);
}
#define SIZE_ISO_8601 25
static inline bool is_leap_year(int16_t y) {
return ((1970 + y) > 0) &&
!((1970 + y) % 4) &&
(((1970 + y) % 100) || !((1970 + y) % 400));
}
static inline int32_t days_in_year(int16_t y) {
return is_leap_year(y) ? 366 : 365;
}
static const uint8_t MONTH_DAYS[]={31,28,31,30,31,30,31,31,30,31,30,31};
static int fill_iso8601_timestamp(int32_t timestamp, int32_t milli,
char* buffer, int* length) {
int16_t year;
int8_t month, month_length;
int32_t day;
int8_t hour, minute, second;
if (*length < SIZE_ISO_8601) {
*length = SIZE_ISO_8601;
return E_BUFFER_TOO_SMALL;
}
second = timestamp % 60;
timestamp /= 60; // now it is minutes
minute = timestamp % 60;
timestamp /= 60; // now it is hours
hour = timestamp % 24;
timestamp /= 24; // now it is days
year = 0;
day = 0;
while ((day += days_in_year(year)) <= timestamp) {
year++;
}
day -= days_in_year(year);
timestamp -= day; // now it is days in this year, starting at 0
day = 0;
month_length = 0;
for (month = 0; month < 12; month++) {
if (month == 1) {
// February
month_length = is_leap_year(year) ? 29 : 28;
} else {
month_length = MONTH_DAYS[month];
}
if (timestamp >= month_length) {
timestamp -= month_length;
} else {
break;
}
}
year = 1970 + year;
month++; // offset by 1
day = timestamp + 1;
int i = 0, j = 0;
// NOTE: It seems the snprintf implementation in Arduino has bugs,
// we have to manually piece the string together here.
#define INT_TO_STR(v_, width_) \
for (j = 0; j < (width_); j++) { \
buffer[i + (width_) - 1 - j] = '0' + ((v_) % 10); \
(v_) /= 10; \
} \
i += (width_)
INT_TO_STR(year, 4);
buffer[i++] = '-';
INT_TO_STR(month, 2);
buffer[i++] = '-';
INT_TO_STR(day, 2);
buffer[i++] = 'T';
INT_TO_STR(hour, 2);
buffer[i++] = ':';
INT_TO_STR(minute, 2);
buffer[i++] = ':';
INT_TO_STR(second, 2);
buffer[i++] = '.';
INT_TO_STR(milli, 3);
buffer[i++] = 'Z';
buffer[i++] = '\0';
#undef INT_TO_STR
*length = i;
return E_OK;
}
