Skip to content

clock_header.tc

clock_header.tc — reusable WebUI clock header

Source on GitHub

// ─────────────────────────────────────────────────────────────────────
// clock_header.tc — reusable WebUI clock header
//
// Renders a big green HH:MM:SS clock at the top of the Tasmota main
// page, with date / weekday / sunrise+sunset row beneath, plus a small
// live-tick badge that proves the AJAX `/?m=1` poll is firing.
//
// This file is **a copy-paste source**, not an importable library —
// TinyC has no `#include` mechanism for `.tc` source files. Two ways
// to use it:
//
//   A) Run it as its own slot — gives you a clock-only main page,
//      handy for testing display layouts or as a status-board page
//      on a spare device.
//
//   B) Paste the marked block into your own script. Look for the
//      `─── BEGIN CLOCK HEADER BLOCK ───` / `─── END CLOCK HEADER
//      BLOCK ───` markers below. Then call `web_clock_header()`
//      from your own `WebCall()`. The block's only external
//      requirement is a `char scratch[256]` buffer in scope —
//      most scripts already have one for sprintf-into-webSend.
//
// Pattern lifted from the original Scripter `>W` clock block (German
// weekday + month abbreviations) so existing Scripter dashboards port
// 1:1. The live-tick badge is new — independent of `tasm_second`,
// which can stall or jump on RTC drift / DST corrections.
//
// Used by: examples/energy_dashboard.tc, examples/powerwall.tc
// ─────────────────────────────────────────────────────────────────────

// ═══════════════ BEGIN CLOCK HEADER BLOCK (copy from here) ═══════════
// Required: a `char scratch[256]` buffer in scope.

int web_clock_tick = 0;            // increments per WebCall poll

void web_clock_header() {
    web_clock_tick = web_clock_tick + 1;

    // Indexed lookup via the built-in `strToken(dst, src, delim, n)`
    // syscall — 1-based index, which lines up directly with
    // tasm_wday (1=Sun..7=Sat) and tasm_month (1..12). Replaces the
    // previous if/else cascade and the Scripter-style `is()`/`is1()`
    // builtins. Generally useful for any small indexed lookup
    // (weekdays, months, status codes, error tables).
    char wd_names[] = "So|Mo|Di|Mi|Do|Fr|Sa";
    char mo_names[] = "Jan|Feb|Mar|Apr|Mai|Jun|Jul|Aug|Sep|Okt|Nov|Dez";
    char wd_label[4];
    char mo_label[4];
    strToken(wd_label, wd_names, '|', tasm_wday);
    strToken(mo_label, mo_names, '|', tasm_month);

    // Single dark-grey rounded card spanning both columns. Contains
    // the big green clock, date row with live-tick badge, and the
    // sunrise → daylight → sunset row. Emitted as raw `<tr><td>` so
    // the whole thing is one full-width centered card (the {s}...{e}
    // tags would split it into label/value columns instead).
    // Two sprintfs because the full card exceeds the 256-byte
    // scratch buffer; first call opens the card + emits clock+date,
    // second call appends the sun row + closes the card.
    sprintf(scratch, "<tr><td colspan=2 style='text-align:center;background:#333;padding:8px;border-radius:8px'><span style='color:green;font-size:40px;font-weight:bold'>%02d:%02d:%02d</span><br>%s %d. %s %d <span style='font-size:0.7em;color:#888;'>&#9679; %d</span><br>",
            tasm_hour, tasm_minute, tasm_second,
            wd_label, tasm_day, mo_label, tasm_year, web_clock_tick);
    webSend(scratch);

    // Sunrise / sunset row with day-length between the arrows, then
    // close the card.
    int sr = tasm_sunrise;
    int ss = tasm_sunset;
    int dl = ss - sr;
    sprintf(scratch, "&#127774; %02d:%02d <--- %02d:%02d ---> %02d:%02d &#127769;</td></tr>",
            sr / 60, sr % 60,
            dl / 60, dl % 60,
            ss / 60, ss % 60);
    webSend(scratch);
}

// ═══════════════ END CLOCK HEADER BLOCK (copy to here) ═══════════════


// ── Standalone-demo glue (only used when this file runs as its own
//    slot; ignore when pasting the block into another script) ──

char scratch[256];

void WebCall() {
    web_clock_header();
}

int main() {
    addLog("clock_header: standalone demo — see / for the clock");
    return 0;
}