Andrew Boyson / web

Dependents:   oldheating gps motorhome heating

Revision:
94:d7226b2c14b6
Parent:
77:4689596a2f3f
Child:
95:8c9dda8a0caf
diff -r 8995561d995f -r d7226b2c14b6 clock/http-clock-script.inc
--- a/clock/http-clock-script.inc	Fri Apr 12 14:12:02 2019 +0000
+++ b/clock/http-clock-script.inc	Tue Apr 16 19:18:27 2019 +0000
@@ -1,224 +1,183 @@
+"//Clock script\n"
 "'use strict';\n"
 "\n"
-"var response        = '';\n"
-"var headers         = '';\n"
-"var msRtc           = 0;     //nibbles  0 to  3: 16 bits\n"
-"var msCountAtRtcSet = 0;\n"
-"var msDiff          = 0;\n"
-"var rtcIsSet        = false; //nibble   4      : bit 0\n"
-"var clockIsSet      = false; //nibble   4      : bit 1\n"
-"var sourceIsOk      = false; //nibble   4      : bit 2\n"
-"var rateIsLocked    = false; //nibble   4      : bit 3\n"
-"var timeIsLocked    = false; //nibble   5      : bit 0\n"
-"var leapEnable      = false; //nibble   5      : bit 1\n"
-"var leapForward     = false; //nibble   5      : bit 2\n"
-"var leapmonths1970  = 0;     //nibbles  6 to  8: 12 bits\n"
-"var leapmonth       = 0;\n"
-"var leapyear        = 0;\n"
-"var leaps           = 0;     //nibbles  9 to 12: 16 bits\n"
-"var ppb             = 0;     //nibbles 13 to 20: 32 bits\n"
-"var scanavg         = 0;     //nibbles 21 to 28: 32 bits\n"
-"var scanmax         = 0;     //nibbles 29 to 36: 32 bits\n"
-"var scanmin         = 0;     //nibbles 37 to 44: 32 bits\n"
-"var msCount         = 0;\n"
+"let pseudo          = new Utc();\n"
+"let rtc             = new Utc();\n"
+"\n"
+"let pseudoDisplay   = false;\n"
+"let pseudoStartMs   = 0;\n"
+"\n"
+"let diffMs          = 0;\n"
+"let rtcIsSet        = false;\n"
+"let clockIsSet      = false;\n"
+"let sourceIsOk      = false;\n"
+"let rateIsLocked    = false;\n"
+"let timeIsLocked    = false;\n"
+"let leapmonths1970  = 0;\n"
 "\n"
-"const         TICK_MS =   100;\n"
-"const AJAX_REFRESH_MS = 10000;\n"
-"const   AJAX_QUIET_MS =  3000;\n"
+"let ppb             = 0;\n"
+"let ppbdivisor      = 0;\n"
+"let ppbmaxchange    = 0;\n"
+"let syncedlimitppb  = 0;\n"
+"let syncedhysppb    = 0;\n"
+"let slewdivisor     = 0;\n"
+"let slewmax         = 0;\n"
+"let syncedlimitns   = 0;\n"
+"let syncedhysns     = 0;\n"
+"let maxoffsetsecs   = 0;\n"
+"let govTrace        = false;\n"
 "\n"
-"function hexToBit(iChar, iBit)\n"
-"{\n"
-"   var value = parseInt(response.charAt(iChar), 16);\n"
-"   value >>= iBit;\n"
-"   return value & 1;\n"
-"}\n"
-"function parseAjax()\n"
+"let ntpserver       = '';\n"
+"let ntpinitial      = 0;\n"
+"let ntpnormal       = 0;\n"
+"let ntpretry        = 0;\n"
+"let ntpoffset       = 0;\n"
+"let ntpmaxdelay     = 0;\n"
+"\n"
+"let scanavg         = 0;\n"
+"let scanmax         = 0;\n"
+"let scanmin         = 0;\n"
+"\n"
+"const DISPLAY_LEAP_MS = 10000;\n"
+"const          SERVER = '/clock-ajax';\n"
+"\n"
+"function parseDate()\n"
 "{\n"
-"   var iDateStart  = headers.toLowerCase().indexOf('date:');\n"
-"   var iDateEnd    = headers.indexOf('\\r', iDateStart);\n"
-"   var rtcDate     = new Date(headers.slice(iDateStart + 5, iDateEnd));\n"
-"   msRtc           = parseInt(response.substr(0, 4), 16);\n"
-"   msRtc          += rtcDate.getTime();\n"
-"   msDiff          = msRtc - Date.now();\n"
-"   msCountAtRtcSet = msCount;\n"
-"   rtcIsSet        = hexToBit(4, 0);\n"
-"   clockIsSet      = hexToBit(4, 1);\n"
-"   sourceIsOk      = hexToBit(4, 2);\n"
-"   rateIsLocked    = hexToBit(4, 3);\n"
-"   timeIsLocked    = hexToBit(5, 0);\n"
-"   leapEnable      = hexToBit(5, 1);\n"
-"   leapForward     = hexToBit(5, 2);\n"
-"   leapmonths1970  = parseInt(response.substr(6, 3), 16);\n"
-"   leapmonth       =  leapmonths1970              % 12;\n"
-"   leapyear        = (leapmonths1970 - leapmonth) / 12;\n"
-"   leapmonth      += 1;\n"
-"   leapyear       += 1970;\n"
-"   leaps           = parseInt(response.substr( 9, 4), 16);\n"
-"   ppb             = parseInt(response.substr(13, 8), 16);\n"
-"   scanavg         = parseInt(response.substr(21, 8), 16);\n"
-"   scanmax         = parseInt(response.substr(29, 8), 16);\n"
-"   scanmin         = parseInt(response.substr(37, 8), 16);\n"
-"}\n"
-"function displayGeneral()\n"
-"{\n"
-"   var elem;\n"
-"   elem = document.getElementById('ajax-rtc-set'      ); if (elem) elem.setAttribute('dir', rtcIsSet     ? 'rtl' : 'ltr');\n"
-"   elem = document.getElementById('ajax-clock-set'    ); if (elem) elem.setAttribute('dir', clockIsSet   ? 'rtl' : 'ltr');\n"
-"   elem = document.getElementById('ajax-source-ok'    ); if (elem) elem.setAttribute('dir', sourceIsOk   ? 'rtl' : 'ltr');\n"
-"   elem = document.getElementById('ajax-rate-locked'  ); if (elem) elem.setAttribute('dir', rateIsLocked ? 'rtl' : 'ltr');\n"
-"   elem = document.getElementById('ajax-time-locked'  ); if (elem) elem.setAttribute('dir', timeIsLocked ? 'rtl' : 'ltr');\n"
-"\n"
-"   elem = document.getElementById('ajax-leap-enable'  ); if (elem) elem.setAttribute('dir', leapEnable   ? 'rtl' : 'ltr');\n"
-"   elem = document.getElementById('ajax-leap-forward' ); if (elem) elem.setAttribute('dir', leapForward  ? 'rtl' : 'ltr');\n"
-"\n"
-"   elem = document.getElementById('ajax-leap-year'    ); if (elem) elem.value = leapmonths1970 ? leapyear  : '';\n"
-"   elem = document.getElementById('ajax-leap-month'   ); if (elem) elem.value = leapmonths1970 ? leapmonth : '';\n"
-"\n"
-"   elem = document.getElementById('ajax-leap-count'   ); if (elem) elem.value = leaps;\n"
-"\n"
-"   elem = document.getElementById('ajax-ppb'          ); if (elem) elem.value = ppb;\n"
-"\n"
-"   elem = document.getElementById('ajax-scan-avg'     ); if (elem) elem.textContent = scanavg;\n"
-"   elem = document.getElementById('ajax-scan-max'     ); if (elem) elem.textContent = scanmax;\n"
-"   elem = document.getElementById('ajax-scan-min'     ); if (elem) elem.textContent = scanmin;\n"
-"\n"
-"   elem = document.getElementById('ajax-response'     ); if (elem) elem.textContent = response;\n"
-"   elem = document.getElementById('ajax-headers'      ); if (elem) elem.textContent = headers;\n"
-"   \n"
-"   elem = document.getElementById('ajax-date-diff'    ); if (elem) elem.textContent = msDiff;\n"
+"    let iDateStart  = BaseHeaders.toLowerCase().indexOf('date:');\n"
+"    let iDateEnd    = BaseHeaders.indexOf('\\r', iDateStart);\n"
+"    let rtcDate     = new Date(BaseHeaders.slice(iDateStart + 5, iDateEnd));\n"
+"    rtc.ms          = rtcDate.getTime();\n"
 "}\n"
 "\n"
-"function formatNumbers00(i)\n"
-"{\n"
-"   if (i<10) i='0' + i;\n"
-"   return i;\n"
-"}\n"
-"function formatDayOfWeek(wday)\n"
+"function parseLinesTime(text)\n"
 "{\n"
-"    switch(wday)\n"
-"    {\n"
-"        case  0: return 'Sun';\n"
-"        case  1: return 'Mon';\n"
-"        case  2: return 'Tue';\n"
-"        case  3: return 'Wed';\n"
-"        case  4: return 'Thu';\n"
-"        case  5: return 'Fri';\n"
-"        case  6: return 'Sat';\n"
-"        default: return '---';\n"
-"    }\n"
+"    let lines = text.split('\\n');\n"
+"    rtc.ms         += parseInt(lines[0], 16);\n"
+"    rtc.ms         -= BaseMs;\n"
+"    diffMs          = rtc.ms + BaseMs - Date.now();\n"
+"    rtcIsSet        = hexToBit(lines[1], 0);\n"
+"    clockIsSet      = hexToBit(lines[1], 1);\n"
+"    sourceIsOk      = hexToBit(lines[1], 2);\n"
+"    rateIsLocked    = hexToBit(lines[1], 3);\n"
+"    timeIsLocked    = hexToBit(lines[1], 4);\n"
+"    rtc.leapEnable  = hexToBit(lines[1], 5);\n"
+"    rtc.leapForward = hexToBit(lines[1], 6);\n"
+"    govTrace        = hexToBit(lines[1], 7);\n"
+"    leapmonths1970  = parseInt(lines[2], 16);\n"
+"    rtc.leapMonth   =  leapmonths1970                  % 12;\n"
+"    rtc.leapYear    = (leapmonths1970 - rtc.leapMonth) / 12;\n"
+"    rtc.leapMonth  += 1;\n"
+"    rtc.leapYear   += 1970;\n"
+"    rtc.leaps       = parseInt(lines[3], 16);\n"
 "}\n"
-"function adjustLeap()\n"
+"function parseLinesGov(text)\n"
 "{\n"
-"    if (msRtc == 0) return; //Don't attempt to adjust an invalid time\n"
-"    \n"
-"    if (!leapEnable) return; // Adjustment disabled\n"
-"    \n"
-"    //Get the calander date and time from the ms\n"
-"    var now       = msCount - msCountAtRtcSet + msRtc;\n"
-"    var leapStart = Date.UTC(leapyear, leapmonth - 1, 1, 0, 0, leapForward ? 0: -1);\n"
-"    \n"
-"    if (now < leapStart) return; //Do nothing until reached the leap start\n"
-"    \n"
-"    if (leapForward) { msRtc -= 1000; leaps += 1; } //repeat 59\n"
-"    else             { msRtc += 1000; leaps -= 1; } //skip   59\n"
-"    \n"
-"    leapEnable = false;\n"
+"    let lines = text.split('\\n');\n"
+"    ppb             = parseInt(lines[0], 16);\n"
+"    ppbdivisor      = parseInt(lines[1], 16);\n"
+"    ppbmaxchange    = parseInt(lines[2], 16);\n"
+"    syncedlimitppb  = parseInt(lines[3], 16);\n"
+"    syncedhysppb    = parseInt(lines[4], 16);\n"
+"    slewdivisor     = parseInt(lines[5], 16);\n"
+"    slewmax         = parseInt(lines[6], 16);\n"
+"    syncedlimitns   = parseInt(lines[7], 16);\n"
+"    syncedhysns     = parseInt(lines[8], 16);\n"
+"    maxoffsetsecs   = parseInt(lines[9], 16);\n"
 "}\n"
-"function displayTime()\n"
+"function parseLinesNtp(text)\n"
+"{\n"
+"    let lines = text.split('\\n');\n"
+"    ntpserver       =          lines[0];\n"
+"    ntpinitial      = parseInt(lines[1], 16);\n"
+"    ntpnormal       = parseInt(lines[2], 16);\n"
+"    ntpretry        = parseInt(lines[3], 16);\n"
+"    ntpoffset       = parseInt(lines[4], 16);\n"
+"    ntpmaxdelay     = parseInt(lines[5], 16);\n"
+"}\n"
+"function parseLinesScan(text)\n"
 "{\n"
-"    if (msRtc == 0) return; //Don't attempt to display an invalid time\n"
+"    let lines = text.split('\\n');\n"
+"    scanavg         = parseInt(lines[0], 16);\n"
+"    scanmax         = parseInt(lines[1], 16);\n"
+"    scanmin         = parseInt(lines[2], 16);\n"
+"}\n"
+"function DerivedParse()\n"
+"{\n"
+"    let topics = BaseResponse.split('\\f');\n"
+"    parseDate();\n"
+"    parseLinesTime(topics[0]);\n"
+"    parseLinesGov (topics[1]);\n"
+"    parseLinesNtp (topics[2]);\n"
+"    parseLinesScan(topics[3]);\n"
+"}\n"
+"function DerivedDisplay()\n"
+"{\n"
+"    let elem;\n"
+"    elem = getElementOrNull('ajax-rtc-set'      ); if (elem) elem.setAttribute('dir', rtcIsSet     ? 'rtl' : 'ltr');\n"
+"    elem = getElementOrNull('ajax-clock-set'    ); if (elem) elem.setAttribute('dir', clockIsSet   ? 'rtl' : 'ltr');\n"
+"    elem = getElementOrNull('ajax-source-ok'    ); if (elem) elem.setAttribute('dir', sourceIsOk   ? 'rtl' : 'ltr');\n"
+"    elem = getElementOrNull('ajax-rate-locked'  ); if (elem) elem.setAttribute('dir', rateIsLocked ? 'rtl' : 'ltr');\n"
+"    elem = getElementOrNull('ajax-time-locked'  ); if (elem) elem.setAttribute('dir', timeIsLocked ? 'rtl' : 'ltr');\n"
 "    \n"
-"    //Get the calander date and time from the ms\n"
-"    var  now = new Date(msCount - msCountAtRtcSet + msRtc);\n"
-"    var    y = now.getUTCFullYear();\n"
-"    var    n = now.getUTCMonth   () + 1;\n"
-"    var    d = now.getUTCDate    ();\n"
-"    var    w = now.getUTCDay     (); // 0 == Sunday\n"
-"    var    h = now.getUTCHours   ();\n"
-"    var    m = now.getUTCMinutes ();\n"
-"    var    s = now.getUTCSeconds ();\n"
-"    \n"
-"    //Format time\n"
-"    n = formatNumbers00(n);\n"
-"    d = formatNumbers00(d);\n"
-"    h = formatNumbers00(h);\n"
-"    m = formatNumbers00(m);\n"
-"    s = formatNumbers00(s);\n"
-"    w = formatDayOfWeek(w);\n"
+"    elem = getElementOrNull('ajax-leap-enable'  ); if (elem) elem.setAttribute('dir', rtc.leapEnable   ? 'rtl' : 'ltr');\n"
+"    elem = getElementOrNull('ajax-leap-forward' ); if (elem) elem.setAttribute('dir', rtc.leapForward  ? 'rtl' : 'ltr');\n"
 "    \n"
-"    //Display time\n"
-"    var elem;\n"
-"        \n"
-"    elem = document.getElementById('ajax-date-utc');\n"
-"    if (elem) elem.textContent = y + '-' + n + '-' + d + ' ' + w + ' ' + h + ':' + m + ':' + s + ' TAI-UTC=' + leaps;\n"
-"\n"
-"    elem = document.getElementById('ajax-date-pc');\n"
-"    var options = \n"
-"    {\n"
-"        year:         'numeric',\n"
-"        month:        'short',\n"
-"        day:          '2-digit',\n"
-"        weekday:      'short',\n"
-"        hour:         '2-digit',\n"
-"        minute:       '2-digit',\n"
-"        second:       '2-digit',\n"
-"        timeZoneName: 'short'\n"
-"    };\n"
-"    if (elem) elem.textContent = now.toLocaleString(undefined, options);\n"
+"    elem = getElementOrNull('ajax-leap-year'    ); if (elem) elem.value = leapmonths1970 ? rtc.leapYear  : '';\n"
+"    elem = getElementOrNull('ajax-leap-month'   ); if (elem) elem.value = leapmonths1970 ? rtc.leapMonth : '';\n"
+"    \n"
+"    elem = getElementOrNull('ajax-leap-count'   ); if (elem) elem.value = rtc.leaps;\n"
+"    \n"
+"    elem = getElementOrNull('ajax-ppb'          ); if (elem) elem.value = ppb;\n"
+"    elem = getElementOrNull('ajax-ppb-divisor'  ); if (elem) elem.value = ppbdivisor;\n"
+"    elem = getElementOrNull('ajax-ppb-max-chg'  ); if (elem) elem.value = ppbmaxchange;\n"
+"    elem = getElementOrNull('ajax-ppb-syn-lim'  ); if (elem) elem.value = syncedlimitppb;\n"
+"    elem = getElementOrNull('ajax-ppb-syn-hys'  ); if (elem) elem.value = syncedhysppb;\n"
+"    elem = getElementOrNull('ajax-off-divisor'  ); if (elem) elem.value = slewdivisor;\n"
+"    elem = getElementOrNull('ajax-off-max'      ); if (elem) elem.value = slewmax;\n"
+"    elem = getElementOrNull('ajax-off-syn-lim'  ); if (elem) elem.value = syncedlimitns / 1000000;\n"
+"    elem = getElementOrNull('ajax-off-syn-hys'  ); if (elem) elem.value = syncedhysns   / 1000000;\n"
+"    elem = getElementOrNull('ajax-off-rst-lim'  ); if (elem) elem.value = maxoffsetsecs;\n"
+"    elem = getElementOrNull('ajax-gov-trace'    ); if (elem) elem.setAttribute('dir', govTrace     ? 'rtl' : 'ltr');\n"
+"    \n"
+"    elem = getElementOrNull('ajax-ntp-server'   ); if (elem) elem.value = ntpserver;\n"
+"    elem = getElementOrNull('ajax-ntp-initial'  ); if (elem) elem.value = ntpinitial;\n"
+"    elem = getElementOrNull('ajax-ntp-normal'   ); if (elem) elem.value = ntpnormal / 60;\n"
+"    elem = getElementOrNull('ajax-ntp-retry'    ); if (elem) elem.value = ntpretry;\n"
+"    elem = getElementOrNull('ajax-ntp-offset'   ); if (elem) elem.value = ntpoffset;\n"
+"    elem = getElementOrNull('ajax-ntp-max-delay'); if (elem) elem.value = ntpmaxdelay;\n"
+"    \n"
+"    elem = getElementOrNull('ajax-scan-avg'     ); if (elem) elem.textContent = scanavg;\n"
+"    elem = getElementOrNull('ajax-scan-max'     ); if (elem) elem.textContent = scanmax;\n"
+"    elem = getElementOrNull('ajax-scan-min'     ); if (elem) elem.textContent = scanmin;\n"
+"    \n"
+"    elem = getElementOrNull('ajax-date-diff'    ); if (elem) elem.textContent = diffMs;\n"
 "}\n"
 "\n"
-"var ajax;\n"
-"var msCountAtAjaxSend = 0;\n"
-"function AjaxRequest(request) //Used by this script and from HTML page\n"
-"{\n"
-"   ajax=new XMLHttpRequest();\n"
-"   ajax.onreadystatechange=handleAjaxResponse;\n"
-"   if (request) ajax.open('GET', '/clock-ajax' + '?' + request, true);\n"
-"   else         ajax.open('GET', '/clock-ajax'                , true);\n"
-"   ajax.send();\n"
-"}\n"
-"function requestAjax() //Used in this script\n"
-"{\n"
-"   \n"
-"   AjaxRequest('');\n"
-"   msCountAtAjaxSend = msCount;\n"
-"}\n"
-"\n"
-"function counter()\n"
+"function DerivedTick() //This typically called every 100ms\n"
 "{\n"
-"    msCount += TICK_MS; //Don't use Date.now() as we don't know when its clock will be updated around a leap second\n"
-"    adjustLeap();\n"
-"    displayTime();\n"
-"    if (msCount >= msCountAtRtcSet + AJAX_REFRESH_MS && //Wait until time to refresh\n"
-"        msCount >= msCountAtAjaxSend + AJAX_QUIET_MS) //Don't repeat during quiet period\n"
+"    if (pseudoDisplay)\n"
 "    {\n"
-"        requestAjax(); //RequestAjax will set msRtc and reset msCount\n"
+"        pseudo.adjustLeap (BaseMs);\n"
+"        pseudo.displayTime(BaseMs);\n"
+"        if (BaseMs >= pseudoStartMs + DISPLAY_LEAP_MS + 500) pseudoDisplay = false;\n"
 "    }\n"
-"}\n"
-"\n"
-"function handleAjaxResponse()\n"
-"{\n"
-"   if (ajax.readyState==4 && ajax.status==200)\n"
-"   {\n"
-"       response = ajax.responseText;\n"
-"       headers  = ajax.getAllResponseHeaders();\n"
-"       parseAjax();\n"
-"       displayGeneral();\n"
-"   }\n"
+"    else\n"
+"    {\n"
+"        rtc.adjustLeap (BaseMs);\n"
+"        rtc.displayTime(BaseMs);\n"
+"    }\n"
 "}\n"
 "\n"
 "function DisplayLeap() //Called by display leap button in HTML\n"
 "{\n"
-"   leapEnable      = true;\n"
-"   msRtc           = Date.UTC(leapyear, leapmonth - 1, 1) - AJAX_REFRESH_MS / 2; //displays the refresh period around the latest leap second\n"
-"   msCountAtRtcSet = msCount;\n"
+"   pseudoDisplay = true;\n"
+"   pseudoStartMs = BaseMs;\n"
+"   \n"
+"   pseudo.leapEnable  = true;\n"
+"   pseudo.leapForward = rtc.leapForward;\n"
+"   pseudo.leaps       = rtc.leaps;\n"
+"   pseudo.leapMonth   = rtc.leapMonth;\n"
+"   pseudo.leapYear    = rtc.leapYear;\n"
+"   pseudo.ms          = Date.UTC(rtc.leapYear, rtc.leapMonth - 1, 1) - DISPLAY_LEAP_MS / 2 - BaseMs;\n"
 "}\n"
-"\n"
-"function init()\n"
-"{\n"
-"    setInterval(counter, TICK_MS);\n"
-"    requestAjax();\n"
-"}\n"
-"if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init ); // Loading hasn't finished yet\n"
-"else                                                                                 init(); //`DOMContentLoaded` has already fired\n"
 ""
\ No newline at end of file