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
M2XStreamClient.cpp
- Committer:
- citrusbyte
- Date:
- 2015-12-28
- Revision:
- 17:9db4a86b876a
- Parent:
- 16:7903152de19f
- Child:
- 19:4dfa28d37b8f
File content as of revision 17:9db4a86b876a:
#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, we reset the server timestamp recorded.
// Notice that unlike Arduino, mbed would overflow every 30 minutes,
// so if 2 calls to this API are more than 30 minutes apart, we are
// likely to run into troubles. This is a limitation of the current
// mbed platform. However, we argue that it might be a rare case that
// 2 calls to this are 30 minutes apart. In most cases, we would call
// this API every few seconds or minutes, this won't be a huge problem.
// However, if you have a use case that would require 2 intervening
// calls to this be 30 minutes apart, you might want to leverage a RTC
// clock instead of the simple ticker here.
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 cannot last 30 minutes, 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;
}
