]> average.org Git - ThermoBeaconDisplay.git/commitdiff
WIP cleanup cache maintnance
authorEugene Crosser <crosser@average.org>
Tue, 23 Jul 2024 10:24:20 +0000 (12:24 +0200)
committerEugene Crosser <crosser@average.org>
Tue, 23 Jul 2024 18:16:40 +0000 (20:16 +0200)
ThermoBeaconDisplay.ino

index bb01988464465c1e097aebe8e61ca6bb69f507ca..58dfdb727e81942b438fe7ccac08e48ca00107d0 100644 (file)
 #include <SPI.h>
 #include <TFT_eSPI.h>
 
+TFT_eSPI tft = TFT_eSPI();
+
 #define SLOTS 2
 #define MAXAGE 100
 
 struct entry {
-  struct entry *next;
   char addr[12];
   int bat;
   int tmp;
   int hum;
   int ticks;
   int rssi;
-  int age;
 };
 
-struct entry *head;
-
-String viewports[] = { "00:00:0b:15", "00:00:01:40" };
+struct elem {
+  struct elem *next;
+  int age;
+  struct entry entry;
+};
 
-TFT_eSPI tft = TFT_eSPI();
+struct elem *head = NULL;
 
-void displayT(String addr, int bat, int tmp, int hum, int ticks, int rssi) {
+void dbgEntry(struct entry *entry) {
+  if (entry) {
+    Serial.print(entry->addr);
+    Serial.print(" Bat: ");
+    Serial.print(entry->bat);
+    Serial.print(" Temp: ");
+    Serial.print(entry->tmp);
+    Serial.print(" Hum: ");
+    Serial.print(entry->hum);
+    Serial.print(" Tm: ");
+    Serial.print(entry->ticks);
+    Serial.print(" Rssi: ");
+    Serial.print(entry->rssi);
+  } else {
+    Serial.print("<NULL ENTRY>");
+  }
+}
 
-  for (int i = 0; i <= 1; i++) {
-    if (viewports[i] == addr) {
-      tft.setViewport(i * (tft.width() / 2) + 4, 4, tft.width() / 2 - 8, tft.height() - 8);
-    }
+void dbgOp(int pos, String str1, struct entry* entry1,
+                    String str2, struct entry* entry2) {
+  Serial.print("pos ");
+  Serial.print(pos);
+  Serial.print(" ");
+  Serial.print(str1);
+  Serial.print(" ");
+  dbgEntry(entry1);
+  if (str2) {
+    Serial.print(" ");
+    Serial.print(str2);
+    Serial.print(" ");
+    dbgEntry(entry2);
   }
+  Serial.println();
+}
+
+void display(int pos, entry *oldval, entry* newval) {
+  if (!newval) return;
+  tft.setViewport(pos * (tft.width() / 2) + 4, 4,
+                  tft.width() / 2 - 8, tft.height() - 8);
   tft.fillScreen(TFT_BLACK);
   tft.setCursor(0, 0, 4);
   tft.setTextColor(TFT_WHITE);
   tft.setTextSize(1);
-  tft.println(addr.substring(3));
+  tft.println(newval->addr + 3);
   tft.setTextColor(TFT_RED);
   tft.setTextSize(2);
-  tft.print(tmp / 10);
+  tft.print(newval->tmp / 10);
   tft.print(".");
-  tft.println(tmp % 10);
+  tft.println(newval->tmp % 10);
   tft.setTextColor(TFT_BLUE);
-  tft.print(hum / 10);
+  tft.print(newval->hum / 10);
   tft.print(".");
-  tft.println(hum % 10);
+  tft.println(newval->hum % 10);
   // tft.setTextColor(TFT_GREEN);
   // tft.setTextSize(1);
-  // tft.print(bat / 100);
+  // tft.print(newval->bat / 100);
   // tft.print(".");
-  // tft.print(bat % 100);
+  // tft.print(newval->bat % 100);
   // tft.print(" ");
-  // tft.println(rssi);
+  // tft.println(newval->rssi);
   tft.resetViewport();
 }
 
-void updateCache(String addr, int bat, int tmp, int hum, int ticks, int rssi) {
-  struct entry *update = NULL;
-  struct entry **cur_p = &head;
-  struct entry *cur = *cur_p;
-  struct entry *slots[SLOTS] = {NULL};
+void updateCache(struct entry *newentry) {
+  struct elem **cur_p = &head;
+  struct elem *cur = *cur_p;
+  struct elem *slots[SLOTS] = {NULL};
+  struct elem *target = NULL;
   int pos = 0;
-  bool needinsert = true;
-  bool mayupdate = true;
-  struct entry nentry;
   
-  while (cur) {
+  while (true) {
+    bool at_the_end = !cur;
     if (pos < SLOTS) slots[pos] = cur;
-    if (strcmp(cur->addr, addr.c_str()) == 0) {
-      Serial.print("found same address ");
-      Serial.print(addr);
-      Serial.print(" at pos ");
-      Serial.println(pos);
-      if (mayupdate && ((cur->rssi <= rssi) || !cur->next || (cur->next->rssi <= rssi))) {
-        Serial.print("at suitable insertion point at pos ");
-        Serial.print(pos);
-        Serial.print(" new rssi ");
-        Serial.print(rssi);
-        Serial.print(" current rssi ");
-        Serial.print(cur->rssi);
-        Serial.print(" next rssi ");
-        Serial.println(cur->next ? cur->next->rssi : 999999);
-        needinsert = false;
-        update = cur;
-        nentry = (struct entry) {
-          .bat = bat,
-          .hum = hum,
-          .ticks = ticks,
-          .rssi = rssi
-          };
-        strncpy(nentry.addr, addr.c_str(), sizeof(nentry.addr));
-        nentry.addr[sizeof(nentry.addr) - 1] = '\0';
+    // First handle insertion because it _can_ happen with cur == NULL
+    if (at_the_end || cur->entry.rssi < newentry->rssi) {
+      dbgOp(pos, "potentially insert", newentry,
+                 "before", cur ? &(cur->entry) : NULL);
+      if (cur && strcmp(cur->entry.addr, newentry->addr) == 0) {
+        dbgOp(pos, "update instead of insert", newentry,
+                   "replacing", &(cur->entry));
+        target = cur;
       } else {
-        Serial.print("removing same address at pos ");
-        Serial.println(pos);
-        (*cur_p) = cur->next;
-        free(cur);
-        cur = *cur_p;
-        if (pos < SLOTS) slots[pos] = NULL;
+        if (target) {
+          dbgOp(pos, "not inserting because update scheduled", newentry,
+                     "before", cur ? &(cur->entry) : NULL);
+        } else {
+          dbgOp(pos, "really insert", newentry,
+                     "before", cur ? &(cur->entry) : NULL);
+          (*cur_p) = (struct elem*)malloc(sizeof(struct elem));
+          (*cur_p)->next = cur;
+          (*cur_p)->age = 0;
+          (*cur_p)->entry = *newentry;
+        }
       }
     }
-    if (cur->age > MAXAGE) {
-        Serial.print("removing old age pos ");
-        Serial.println(pos);
-        (*cur_p) = cur->next;
-        free(cur);
-        cur = *cur_p;
-        if (pos < SLOTS) slots[pos] = NULL;
-    } else {
-      Serial.print("Increaing age for ");
-      Serial.println(cur->addr);
-      cur->age++;
-    }
-    if (needinsert && (cur->rssi < rssi)) {
-      Serial.print("inserting addr ");
-      Serial.print(addr);
-      Serial.print(" at pos ");
-      Serial.println(pos);
-      (*cur_p) = (struct entry*)malloc(sizeof(struct entry));
-      (**cur_p) = (struct entry) {
-        .next = cur,
-        .bat = bat,
-        .hum = hum,
-        .ticks = ticks,
-        .rssi = rssi
-      };
-      strncpy((*cur_p)->addr, addr.c_str(), sizeof(nentry.addr));
-      (*cur_p)->addr[sizeof(nentry.addr) - 1] = '\0';
-      needinsert = false;
-      mayupdate = false;
+    if (at_the_end) break;
+    // The rest of the operations in the loop assume that `cur` exists
+    (cur->age)++;
+    if (strcmp(cur->entry.addr, newentry->addr) == 0 || cur->age > MAXAGE) {
+      dbgOp(pos, "potentially delete", &(cur->entry), "", NULL);
+      if (target == cur) {
+        dbgOp(pos, "do not delete", &(cur->entry),
+                   "scheduled for replacement by", newentry);
+      } else {
+        if (strcmp(cur->entry.addr, newentry->addr) == 0 &&
+            (!(cur->next) || cur->next->entry.rssi < newentry->rssi)) {
+          dbgOp(pos, "update instead of delete", &(cur->entry),
+                     "already at the insersion point for", newentry);
+          target = cur;
+        } else {
+          dbgOp(pos, "really delete", &(cur->entry), "", NULL);
+          (*cur_p) = cur->next;
+          free(cur);
+          cur = *cur_p;
+          if (pos < SLOTS) slots[pos] = NULL;
+          pos--;  // This may make it negative, but it will be bumped up next
+        }
+      }
     }
+    // Proceed to the next element of the list
     cur_p = &(cur->next);
     cur = *cur_p;
     pos++;
   }
-  if (needinsert) {
-    Serial.print("inserting addr ");
-    Serial.print(addr);
-    Serial.println(" at the tail");
-    (*cur_p) = (struct entry*)malloc(sizeof(struct entry));
-    (**cur_p) = (struct entry) {
-      .next = cur,
-      .bat = bat,
-      .hum = hum,
-      .ticks = ticks,
-      .rssi = rssi
-    };
-    strncpy((*cur_p)->addr, addr.c_str(), sizeof(nentry.addr));
-    (*cur_p)->addr[sizeof(nentry.addr) - 1] = '\0';
-  }
+  // Finished modifying the list, now display
   for (cur = head, pos = 0; pos < SLOTS; cur = cur ? cur->next : cur, pos++) {
-    if (update && (slots[pos] == update)) {
+    if (target && (slots[pos] == target)) {
       // old = slots[pos], new = nentry
-      Serial.print("Display as updated pos ");
-      Serial.print(pos);
-      Serial.print(" addr was ");
-      Serial.print(slots[pos] ? slots[pos]->addr : "NONE");
-      Serial.print(" now ");
-      Serial.println(nentry.addr);
+      dbgOp(pos, "Display before updating, old", slots[pos] ? &(slots[pos]->entry) : NULL,
+                 "new", newentry);
+      display(pos, slots[pos] ? &(slots[pos]->entry) : NULL, newentry);
     } else {
       //old = slots[pos], new = cur
-      Serial.print("Display as new pos ");
-      Serial.print(pos);
-      Serial.print(" addr was ");
-      Serial.print(slots[pos] ? slots[pos]->addr : "NONE");
-      Serial.print(" now ");
-      Serial.println(cur ? cur->addr : "NULL");
+      dbgOp(pos, "Display as different elems, old", slots[pos] ? &(slots[pos]->entry) : NULL,
+                 "new", cur ? &(cur->entry) : NULL);
+      display(pos, slots[pos] ? &(slots[pos]->entry) : NULL, cur ? &(cur->entry) : NULL);
     }
   }
-  if (update) {
-    update->bat = nentry.bat;
-    update->hum = nentry.hum;
-    update->ticks = nentry.ticks;
-    update->rssi = nentry.rssi;
-    update->age = 0;
+  // Now we can actually update the entry
+  if (target) {
+    target->entry = *newentry;
+    target->age = 0;
   }
-  displayT(addr, bat, tmp, hum, ticks, rssi);
 }
 
-void dbg(BLEDevice peripheral) {
+void dbgDevEv(BLEDevice peripheral) {
+#if 0
   Serial.print("Address: ");
   Serial.println(peripheral.address());
   Serial.print("RSSI: ");
@@ -210,35 +204,28 @@ void dbg(BLEDevice peripheral) {
     Serial.println();
   }
   Serial.println();
+#endif
 }
 
 void advHandler(BLEDevice dev) {
   if (dev.address().substring(0,6) == "a3:e4:") {
-    // dbg(dev);
+    dbgDevEv(dev);
     if (dev.hasManufacturerData()) {
       int len = dev.manufacturerDataLength();
       if (len == 20) {
         uint8_t buf[20];
         dev.manufacturerData(buf, len);
-        int bat = ((buf[11] << 8) + buf[10]) / 10;
-        int tmp = ((buf[13] << 8) + buf[12]) * 10 / 16;
-        int hum = ((buf[15] << 8) + buf[14]) * 10 / 16;
-        uint32_t ticks = (buf[18] << 16) + (buf[17] << 8) + buf[16];
-        /*
-        Serial.print(dev.address());
-        Serial.print(" Bat: ");
-        Serial.print(bat);
-        Serial.print(" Temp: ");
-        Serial.print(tmp);
-        Serial.print(" Hum: ");
-        Serial.print(hum);
-        Serial.print(" Tm: ");
-        Serial.print(ticks);
-        Serial.print(" Rssi: ");
-        Serial.print(dev.rssi());
-        Serial.println();
-        */
-        updateCache(dev.address().substring(6), bat, tmp, hum, ticks, dev.rssi());
+        struct entry newentry = {
+          .bat = ((buf[11] << 8) + buf[10]) / 10,
+          .tmp = ((buf[13] << 8) + buf[12]) * 10 / 16,
+          .hum = ((buf[15] << 8) + buf[14]) * 10 / 16,
+          .ticks = (buf[18] << 16) + (buf[17] << 8) + buf[16],
+          .rssi = dev.rssi()
+        };
+        strncpy(newentry.addr, dev.address().substring(6).c_str(),
+                sizeof(newentry.addr));
+        newentry.addr[sizeof(newentry.addr) - 1] = '\0';
+        updateCache(&newentry);
       }
     }
   }
@@ -251,8 +238,7 @@ void setup() {
     Serial.println("starting Bluetooth® Low Energy module failed!");
     while (1);
   }
-  BLE.setEventHandler(BLEDiscovered, advHandler);
-  BLE.scan(true);
+
   tft.init();
   tft.setRotation(1);
   tft.fillScreen(TFT_BLACK);
@@ -262,6 +248,9 @@ void setup() {
   tft.setViewport(tft.width() / 2, 0, tft.width() / 2, tft.height());
   tft.frameViewport(TFT_NAVY, 1);
   tft.resetViewport();
+
+  BLE.setEventHandler(BLEDiscovered, advHandler);
+  BLE.scan(true);
 }
 
 void loop() {