     last_doorstatechange = millis();
   }
 
+  // catch any logic errors or strange cases where the door is open while we think
+  // we are not doing anything.
+  //
+  if ((millis() - last_doorstatechange > 10 * DOOR_OPEN_DELAY) && ((doorstate != CLOSED) || (!isClosed()))) {
+    closeDoor();
+    char msg[256];
+    snprintf(msg, sizeof(msg), "[%s] Door in an odd state - forcing close.", pname);
+    Serial.println(msg);
+    client.publish(log_topic, msg);
+    cnt_fails ++;
+  }
+
   if (millis() - tock  > REPORTING_PERIOD) {
     char buff[1024];
     cnt_minutes += ((millis() - tock) + 500) / 1000 / 60;
-
-    snprintf(buff, sizeof(buff),
-             "[%s] alive - uptime %02ld:%02ld: "
-             "swipes %ld, opens %ld, closes %ld, fails %ld, mis-swipes %ld, mqtt reconnects %ld",
-             pname, cnt_minutes / 60, (cnt_minutes % 60),
-             cnt_cards,
-             cnt_opens, cnt_closes, cnt_fails, cnt_misreads, cnt_reconnects);
-    client.publish(log_topic, buff);
-    Serial.println(buff);
+    reportStats();
     tock = millis();
   }
 
   if (irqCardSeen) {
     if (mfrc522.PICC_ReadCardSerial()) {
-      MFRC522::Uid uid = mfrc522.uid;
+      uid = mfrc522.uid;
       cnt_cards++;
 
       String uidStr = "";


#define DOOR_CLOSED       (0)
#define DOOR_OPEN         (1100)
#define DOOR_OPEN_DELAY   (10*1000)

#define REPORTING_PERIOD  (300*1000)

typedef enum doorstates { CLOSED, OPENING, OPEN, CLOSING } doorstate_t;
doorstate_t doorstate;
unsigned long long last_doorstatechange = 0;

long cnt_cards = 0, cnt_opens = 0, cnt_closes  = 0, cnt_fails = 0, cnt_misreads = 0, cnt_minutes = 0, cnt_reconnects = 0;

#include <ETH.h>
#include <SPI.h>

#include <ArduinoOTA.h>
#include <AccelStepper.h>


  static doorstate_t lastdoorstate = CLOSED;
  switch (doorstate) {
    case CHECKINGCARD:
      if (millis() - last_doorstatechange > 1500 && caching && checkCache(uid)) {
        char msg[255];
        snprintf(msg, sizeof(msg), "[%s] Allowing door to open based on cached information.", pname);
        Serial.println(msg);
        client.publish(log_topic, msg);
        openDoor();
      }
      break;
    case OPENING:
      if (isOpen()) {
        char msg[256];
        snprintf(msg, sizeof(msg), "[%s] Door is open.", pname);
        Serial.println(msg);
