 void reportStats() {
   char buff[255];
   snprintf(buff, sizeof(buff),
-           "[%s] alive-uptime %02ld:%02ld "
-           "mqtt: %s (state %d) "
+           "[%s] alive-uptime %02ld:%02ld, "
+           "mqtt %s (state %d) "
            "swipes %ld, opens %ld, closes %ld, fails %ld, mis-swipes %ld, mqtt reconnects %ld, mqtt fails %ld, "
-           "door %s, state %s(%d)",
+           "door %s, state %s(%d), caching %s",
            pname, cnt_minutes / 60, (cnt_minutes % 60),
            client.connected() ? "connected" : "not-connected", client.state(),
            cnt_cards,
            cnt_opens, cnt_closes, cnt_fails, cnt_misreads, cnt_reconnects, cnt_mqttfails,
            isOpen() ? "open" : "closed",
-           doorstates_names[doorstate], doorstate
+           doorstates_names[doorstate], doorstate,
+           caching ? "on" : "off"
           );
   client.publish(log_topic, buff);
   Serial.println(buff);

#define SOLENOID_GPIO     (4)
#define SOLENOID_OFF      (LOW)
#define SOLENOID_ENGAGED  (HIGH)
#define AARTLED_GPIO     (16)

#define DOOR_OPEN_DELAY         (10*1000)   //  10 seconds -- how long to hold the relay engaged; in milli seconds.
#define CACHE_FALLBACK_TIMEOUT  (500)       // 0.5 second  -- how long to wait for a reply before checking the cache.

// Report regulary - but swithc to a higher frequency if we are in test mode. Also prefix our MQTT topic with 'test'
// to avoid confusing production.

        client.publish(log_topic, msg);
        openDoor();
      }
      if (millis() - last_doorstatechange > MAX_RESPONSE_TIMEOUT) {
        char msg[255];
        snprintf(msg, sizeof(msg), "[%s] No reply from server. Keeping door closed.", pname);
        Serial.println(msg);
        client.publish(log_topic, msg);
        closeDoor();
      }
      break;
    case OPEN:
    case CLOSED:
