Skip to content

Commit

Permalink
Add clock status information, separate current status and drift history
Browse files Browse the repository at this point in the history
  • Loading branch information
pascal-fb-martin committed Oct 14, 2019
1 parent 45c2f3a commit c8caf2a
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 49 deletions.
17 changes: 17 additions & 0 deletions hc_clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ static int clockShowDrift = 0;

static int clockSynchronized = 0;

static hc_clock_status *hc_clock_status_db = 0;
static int *hc_clock_drift_db = 0;

const char *hc_clock_help (int level) {
Expand Down Expand Up @@ -98,6 +99,17 @@ void hc_clock_initialize (int argc, const char **argv) {
}
hc_clock_drift_db = (int *) hc_db_get (HC_CLOCK_DRIFT);
for (i = 0; i < 120; ++i) hc_clock_drift_db[i] = 0;

i = hc_db_new (HC_CLOCK_STATUS, sizeof(hc_clock_status), 1);
if (i != 0) {
fprintf (stderr,
"cannot create %s: %s\n", HC_CLOCK_STATUS, strerror(i));
exit (1);
}
hc_clock_status_db = (hc_clock_status *)hc_db_get (HC_CLOCK_STATUS);
hc_clock_status_db->synchronized = 0;
hc_clock_status_db->precision = clockPrecision;
hc_clock_status_db->drift = 0;
}

void hc_clock_synchronize(const struct timeval *gps,
Expand All @@ -109,6 +121,10 @@ void hc_clock_synchronize(const struct timeval *gps,
time_t absdrift = (drift < 0)? (0 - drift) : drift;

if (hc_clock_drift_db) hc_clock_drift_db[local->tv_sec%120] = (int)drift;
if (hc_clock_status_db) {
hc_clock_status_db->drift = (int)drift;
hc_clock_status_db->timestamp = *local;
}

if (clockShowDrift || hc_test_mode()) {
printf ("[%d]=%8.3f\n", local->tv_sec%120, drift/1000.0);
Expand All @@ -117,6 +133,7 @@ void hc_clock_synchronize(const struct timeval *gps,

if (absdrift < clockPrecision) {
clockSynchronized = 1;
if (hc_clock_status_db) hc_clock_status_db->synchronized = 1;
return;
}

Expand Down
9 changes: 9 additions & 0 deletions hc_clock.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,12 @@ int hc_clock_synchronized (void);
*/
#define HC_CLOCK_DRIFT "ClockDrift"

#define HC_CLOCK_STATUS "ClockStatus"

typedef struct {
int synchronized;
int precision;
int drift;
struct timeval timestamp;
} hc_clock_status;

120 changes: 71 additions & 49 deletions hc_http.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,27 +46,28 @@
static pid_t parent;


static char JsonBuffer[8192];

static void hc_background (int fd, int mode) {
if (kill (parent, 0) < 0) exit(0);
}

static void *hc_http_attach (const char *name) {
void *p = hc_db_get (name);
if (p == 0) echttp_error (503, "Service Temporarily Unavailable");
return p;
}

static const char *hc_http_status (const char *method, const char *uri,
const char *data, int length) {
static char buffer[8192];
static char *driftbuffer;
static int driftbuffersize;
static hc_nmea_status *status_db = 0;
static int *drift_db = 0;
static int drift_count;
static hc_nmea_status *nmea_db = 0;
static hc_clock_status *clock_db = 0;
char latitude[20];
char longitude[20];

if (status_db == 0) {
status_db = (hc_nmea_status *) hc_db_get (HC_NMEA_STATUS);
if (status_db == 0) {
echttp_error (503, "Service Temporarily Unavailable");
return "";
}
if (nmea_db == 0) {
nmea_db = (hc_nmea_status *) hc_http_attach (HC_NMEA_STATUS);
if (nmea_db == 0) return "";
if (hc_db_get_count (HC_NMEA_STATUS) != 1
|| hc_db_get_size (HC_NMEA_STATUS) != sizeof(hc_nmea_status)) {
fprintf (stderr, "wrong data structure for table %s\n",
Expand All @@ -75,65 +76,86 @@ static const char *hc_http_status (const char *method, const char *uri,
}
}

if (drift_db == 0) {
drift_db = (int *) hc_db_get (HC_CLOCK_DRIFT);
if (drift_db == 0) {
echttp_error (503, "Service Temporarily Unavailable");
return "";
}
drift_count = hc_db_get_count (HC_CLOCK_DRIFT);
if (hc_db_get_size (HC_CLOCK_DRIFT) != sizeof(int)) {
if (clock_db == 0) {
clock_db = (hc_clock_status *) hc_http_attach (HC_CLOCK_STATUS);
if (clock_db == 0) return "";
if (hc_db_get_count (HC_CLOCK_STATUS) != 1
|| hc_db_get_size (HC_CLOCK_STATUS) != sizeof(hc_clock_status)) {
fprintf (stderr, "wrong data structure for table %s\n",
HC_CLOCK_DRIFT);
HC_CLOCK_STATUS);
exit (1);
}
driftbuffersize = drift_count * 12;
driftbuffer = malloc(driftbuffersize);
}

snprintf (driftbuffer, driftbuffersize, "%d", drift_db[0]);
int room = driftbuffersize - strlen(driftbuffer);
char *p = driftbuffer + (driftbuffersize-room);
int i;
for (i = 1; i < drift_count; ++i) {
snprintf (p, room, ",%d", drift_db[i]);
room -= strlen(p);
p = driftbuffer + (driftbuffersize-room);
}

// This conversion is not made when decoding the NMEA stream to avoid
// consuming CPU in the high-priority time synchronization process.
//
hc_nmea_convert (latitude, sizeof(latitude),
status_db->latitude, status_db->hemisphere[0]);
nmea_db->latitude, nmea_db->hemisphere[0]);
hc_nmea_convert (longitude, sizeof(longitude),
status_db->longitude, status_db->hemisphere[1]);
nmea_db->longitude, nmea_db->hemisphere[1]);

snprintf (buffer, sizeof(buffer),
snprintf (JsonBuffer, sizeof(JsonBuffer),
"{\"gps\":{\"fix\":%s"
",\"time\":[%c%c,%c%c,%c%c],\"date\":[%d,%c%c,%c%c]"
",\"latitude\":%s,\"longitude\":%s,\"timestamp\":%zd.%03d}"
",\"clock\":{\"drift\":[%s]}}",
status_db->fix?"true":"false",
status_db->time[0], status_db->time[1],
status_db->time[2], status_db->time[3],
status_db->time[4], status_db->time[5],
2000 + (status_db->date[4]-'0')*10 + (status_db->date[5]-'0'),
status_db->date[2], status_db->date[3],
status_db->date[0], status_db->date[1],
",\"latitude\":%s,\"longitude\":%s}"
",\"clock\":{\"synchronized\":%s"
",\"precision\":%d,\"drift\":%d,\"timestamp\":%zd.%03d}}",
nmea_db->fix?"true":"false",
nmea_db->time[0], nmea_db->time[1],
nmea_db->time[2], nmea_db->time[3],
nmea_db->time[4], nmea_db->time[5],
2000 + (nmea_db->date[4]-'0')*10 + (nmea_db->date[5]-'0'),
nmea_db->date[2], nmea_db->date[3],
nmea_db->date[0], nmea_db->date[1],
latitude, longitude,
(size_t) (status_db->timestamp.tv_sec),
status_db->timestamp.tv_usec/1000,
driftbuffer);
clock_db->synchronized?"true":"false",
clock_db->precision,
clock_db->drift,
(size_t) (clock_db->timestamp.tv_sec),
clock_db->timestamp.tv_usec/1000);
echttp_content_type_json();
return JsonBuffer;
}

static const char *hc_http_clockdrift (const char *method, const char *uri,
const char *data, int length) {
static int *drift_db = 0;
static int drift_count;

if (drift_db == 0) {
drift_db = (int *) hc_http_attach (HC_CLOCK_DRIFT);
if (drift_db == 0) return "";
drift_count = hc_db_get_count (HC_CLOCK_DRIFT);
if (hc_db_get_size (HC_CLOCK_DRIFT) != sizeof(int)) {
fprintf (stderr, "wrong data structure for table %s\n",
HC_CLOCK_DRIFT);
exit (1);
}
}

snprintf (JsonBuffer, sizeof(JsonBuffer),
"{\"clock\":{\"drift\":[%d", drift_db[0]);

int room = sizeof(JsonBuffer) - strlen(JsonBuffer);
char *p = JsonBuffer + (sizeof(JsonBuffer)-room);
int i;
for (i = 1; i < drift_count; ++i) {
snprintf (p, room, ",%d", drift_db[i]);
room -= strlen(p);
p = JsonBuffer + (sizeof(JsonBuffer)-room);
}
snprintf (p, room, "%s", "]}}");
echttp_content_type_json();
return buffer;
return JsonBuffer;
}

void hc_http (int argc, const char **argv) {
parent = getppid();
if (echttp_open (argc, argv) <= 0) exit(1);

echttp_route_uri ("/status", hc_http_status);
echttp_route_uri ("/clock/drift", hc_http_clockdrift);
echttp_static_route ("/ui", "/usr/local/lib/houseclock/public");
echttp_background (&hc_background);
echttp_loop();
Expand Down

0 comments on commit c8caf2a

Please sign in to comment.