Data em milissegundos no OpenWRT no Arduino YUN

Data em milissegundos no OpenWRT no Arduino YUN

Estou usando OpenWRT no Arduino YUN e estou tentando obter a data exata em milissegundos (DD/MM/AAAA h:min:sec:ms) obtendo a hora por um servidor de tempo.

Infelizmente date +%Napenas retorna %N, mas não os nanossegundos. Ouvi dizer +%Nque não está incluído na data do OpenWRT.

Então, existe alguma maneira de obter a data (incluindo milissegundos) como eu quero?

Responder1

No OpenWRT, dateé busybox, que tem limitações, mas esta não é estritamente uma delas. O problema subjacente é que o libc (uClibc)não suporta esta extensão GNU strftime. (Embora a glibc também não, mais sobre isso abaixo.)

Você deveria ter feito isso luapor padrão, mas issonão vai ajudarsem alguns outros módulos não padrão.

hwclockexige gettimeofday()comparação/configuração do RTC (relógio de hardware), mas não produz resolução abaixo de um segundo (o acesso aos RTCs pode ser lento o suficiente para não ser útil de qualquer maneira). Fora isso, o OpenWRT fornece apenas o antigo rdate, que só tem resolução de segundos inteiros.

Parece não haver uma maneira direta de obter um carimbo de data/hora preciso diretamente do /proc, o carimbo de data/hora mais útil está na /proc/timer_list(3ª linha), que é o tempo de atividade em nanossegundos (a resolução dependerá da plataforma).

Se o seu busybox foi construído com CONFIG_BUSYBOX_CONFIG_ADJTIMEXset, então você poderá usá-lo adjtimexpara ler o relógio do kernel (embora observe que a versão do busybox possuiambosargumentos diferentes e saída diferente para o adjtimex padrão.

Versão normal, adjtimex -púltima linha de saída:

   raw time:  1416419719s 146628us = 1416419719.146628

Versão Busybox, adjtimex(sem -p!), últimas 3 linhas:

   [...]
   time.tv_sec:  1416420386
   time.tv_usec: 732653
   return value: 0 (clock synchronized)

Goldilocks é uma ótima solução, supondo que você tenha sua configuração de construção cruzada OpenWRT (altamente recomendado!). Seudata coreutilsA solução funciona porque, embora o coreutils seja compatível com glibc, não é exclusivamente glibc. Ele vem com sua própria implementação autônoma de strftime(derivada de glibc) e a usa para encerrar (via strftime_case()) o subjacente, strftimede modo a suportar várias extensões (caso contrário, volta para a versão uClibc).

Mesmo que o glibc (até o atual 2.23) não suporte %N, os coreutils strftime()derivados da versão canônica do glibc adicionam %Ne %:zalgumas outras alterações. Variações e versões corrigidas são strftime()abundantes (incluindo versões em bash e gawk).

Responder2

Se você tiver um compilador C instalado e não conseguir encontrar mais nada, isso irá reportar, por exemplo

> millitime && sleep 1 && millitime
14/11/2014 9:39:49:364
14/11/2014 9:39:50:368
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>

int main (void) {
    struct timeval now;
    struct tm *parsed;

    if (gettimeofday(&now, NULL) == -1) {
        fprintf (
            stderr,
            "gettimeofday() failed: %s\n",
            strerror(errno)
        );
        return 1;
    }

    parsed = localtime((const time_t*)&now.tv_sec);
    if (!parsed) {
        fprintf (
            stderr,
            "localtime() failed: %s\n",
            strerror(errno)
        );
        return 1;
    }

    printf (
        "%d/%d/%d %d:%02d:%02d:%03d\n",
        parsed->tm_mday,
        parsed->tm_mon + 1,
        parsed->tm_year + 1900,
        parsed->tm_hour,
        parsed->tm_min,
        parsed->tm_sec,
        now.tv_usec / 1000
    );

    return 0;
}  

Com o gcc, basta compilá-lo gcc whatever.c -o millitime. Se houver um erro (o que seria muito estranho), ele reporta para stderr e sai com status 1. Caso contrário, reporta para stdout e sai 0.

Os milissegundos sãoarredondado para baixode microssegundos.

Responder3

Na verdade, também existe um pacote chamado coreutils-date! Não sabia disso! Todas as funcionalidades padrão estão incluídas!

Responder4

#include <stdio.h>
#include <time.h>
void main (void){
    long            ms; 
    time_t          s; 

    struct timespec spec;
    clock_gettime(CLOCK_REALTIME, &spec);
    s  = spec.tv_sec;
    ms = (spec.tv_nsec / 1.0e6); 
    printf("%d%03d\n", s, ms);      
return 0;
}

Isso na linguagem C e funciona como coreutils-date date +%s%3N. Ele é compilado para roteador OpenWrt com OpenWrt-SDK.

informação relacionada