diff --git a/characters/memes-src/attention.gif b/characters/memes-src/attention.gif new file mode 100644 index 00000000..72df9e2e Binary files /dev/null and b/characters/memes-src/attention.gif differ diff --git a/characters/memes-src/busy.gif b/characters/memes-src/busy.gif new file mode 100644 index 00000000..968d3d4a Binary files /dev/null and b/characters/memes-src/busy.gif differ diff --git a/characters/memes-src/celebrate.gif b/characters/memes-src/celebrate.gif new file mode 100644 index 00000000..ea334a0c Binary files /dev/null and b/characters/memes-src/celebrate.gif differ diff --git a/characters/memes-src/dizzy.gif b/characters/memes-src/dizzy.gif new file mode 100644 index 00000000..b6c651d0 Binary files /dev/null and b/characters/memes-src/dizzy.gif differ diff --git a/characters/memes-src/heart.gif b/characters/memes-src/heart.gif new file mode 100644 index 00000000..4247da9a Binary files /dev/null and b/characters/memes-src/heart.gif differ diff --git a/characters/memes-src/idle.gif b/characters/memes-src/idle.gif new file mode 100644 index 00000000..5dcae1be Binary files /dev/null and b/characters/memes-src/idle.gif differ diff --git a/characters/memes-src/manifest.json b/characters/memes-src/manifest.json new file mode 100644 index 00000000..da20460e --- /dev/null +++ b/characters/memes-src/manifest.json @@ -0,0 +1,17 @@ +{ + "name": "memes", + "colors": { + "bg": "#000000", + "text": "#FFFFFF", + "textDim": "#808080" + }, + "states": { + "sleep": "sleep.gif", + "idle": "idle.gif", + "busy": "busy.gif", + "attention": "attention.gif", + "celebrate": "celebrate.gif", + "dizzy": "dizzy.gif", + "heart": "heart.gif" + } +} diff --git a/characters/memes-src/sleep.gif b/characters/memes-src/sleep.gif new file mode 100644 index 00000000..35103b68 Binary files /dev/null and b/characters/memes-src/sleep.gif differ diff --git a/characters/memes/attention.gif b/characters/memes/attention.gif new file mode 100644 index 00000000..1ee2646d Binary files /dev/null and b/characters/memes/attention.gif differ diff --git a/characters/memes/busy.gif b/characters/memes/busy.gif new file mode 100644 index 00000000..8487ed95 Binary files /dev/null and b/characters/memes/busy.gif differ diff --git a/characters/memes/celebrate.gif b/characters/memes/celebrate.gif new file mode 100644 index 00000000..290be290 Binary files /dev/null and b/characters/memes/celebrate.gif differ diff --git a/characters/memes/dizzy.gif b/characters/memes/dizzy.gif new file mode 100644 index 00000000..b62435d4 Binary files /dev/null and b/characters/memes/dizzy.gif differ diff --git a/characters/memes/heart.gif b/characters/memes/heart.gif new file mode 100644 index 00000000..ac652bf1 Binary files /dev/null and b/characters/memes/heart.gif differ diff --git a/characters/memes/idle.gif b/characters/memes/idle.gif new file mode 100644 index 00000000..2bf8f328 Binary files /dev/null and b/characters/memes/idle.gif differ diff --git a/characters/memes/manifest.json b/characters/memes/manifest.json new file mode 100644 index 00000000..a56660e5 --- /dev/null +++ b/characters/memes/manifest.json @@ -0,0 +1,17 @@ +{ + "name": "memes", + "colors": { + "bg": "#000000", + "text": "#FFFFFF", + "textDim": "#808080" + }, + "states": { + "sleep": "sleep.gif", + "idle": "idle.gif", + "busy": "busy.gif", + "attention": "attention.gif", + "celebrate": "celebrate.gif", + "dizzy": "dizzy.gif", + "heart": "heart.gif" + } +} \ No newline at end of file diff --git a/characters/memes/sleep.gif b/characters/memes/sleep.gif new file mode 100644 index 00000000..ad933268 Binary files /dev/null and b/characters/memes/sleep.gif differ diff --git a/src/ble_bridge.cpp b/src/ble_bridge.cpp index ac692101..2d9b7789 100644 --- a/src/ble_bridge.cpp +++ b/src/ble_bridge.cpp @@ -30,6 +30,12 @@ static volatile bool secure = false; static volatile uint32_t passkey = 0; static volatile uint16_t mtu = 23; +// BD address of the currently connected peer. Set on connect, cleared on +// disconnect. Used by bleRemoveCurrentBond() so "unpair" only removes the +// host that sent the command rather than wiping all stored bonds. +static esp_bd_addr_t peerAddr; +static volatile bool hasPeer = false; + static void rxPush(const uint8_t* p, size_t n) { for (size_t i = 0; i < n; i++) { size_t next = (rxHead + 1) % RX_CAP; @@ -47,15 +53,21 @@ class RxCallbacks : public BLECharacteristicCallbacks { }; class ServerCallbacks : public BLEServerCallbacks { - void onConnect(BLEServer* s) override { + // Use the extended overload to capture the peer BD address. + void onConnect(BLEServer* s, esp_ble_gatts_cb_param_t* param) override { connected = true; - Serial.println("[ble] connected"); + memcpy((void*)peerAddr, param->connect.remote_bda, sizeof(esp_bd_addr_t)); + hasPeer = true; + Serial.printf("[ble] connected %02x:%02x:%02x:%02x:%02x:%02x\n", + peerAddr[0], peerAddr[1], peerAddr[2], + peerAddr[3], peerAddr[4], peerAddr[5]); } void onDisconnect(BLEServer* s) override { connected = false; secure = false; passkey = 0; mtu = 23; + hasPeer = false; Serial.println("[ble] disconnected"); // Restart advertising so the next client can find us. BLEDevice::startAdvertising(); @@ -137,6 +149,17 @@ bool bleConnected() { return connected; } bool bleSecure() { return secure; } uint32_t blePasskey() { return passkey; } +void bleRemoveCurrentBond() { + if (!hasPeer) { + Serial.println("[ble] unpair: no peer to remove"); + return; + } + esp_ble_remove_bond_device(peerAddr); + Serial.printf("[ble] removed bond %02x:%02x:%02x:%02x:%02x:%02x\n", + peerAddr[0], peerAddr[1], peerAddr[2], + peerAddr[3], peerAddr[4], peerAddr[5]); +} + void bleClearBonds() { int n = esp_ble_get_bond_device_num(); if (n <= 0) return; diff --git a/src/ble_bridge.h b/src/ble_bridge.h index 1ea5527b..c777d672 100644 --- a/src/ble_bridge.h +++ b/src/ble_bridge.h @@ -24,8 +24,11 @@ bool bleSecure(); // Non-zero while a 6-digit pairing passkey should be on screen. main.cpp // renders it; cleared automatically on auth complete or disconnect. uint32_t blePasskey(); -// Erase all stored bonds (LTKs) from NVS. Called from the "unpair" cmd -// and from factory reset. +// Remove only the bond for the currently connected peer. Called from the +// "unpair" JSON command so a desktop can unpair itself without affecting +// bonds held by other hosts. +void bleRemoveCurrentBond(); +// Erase ALL stored bonds from NVS. Called only from factory reset. void bleClearBonds(); size_t bleAvailable(); int bleRead(); diff --git a/src/data.h b/src/data.h index 94ec4e34..a575743e 100644 --- a/src/data.h +++ b/src/data.h @@ -174,8 +174,10 @@ inline void dataPoll(TamaState* out) { } } + bool wasConnected = out->connected; out->connected = dataConnected(); if (!out->connected) { + if (wasConnected) _rtcValid = false; // force re-sync on next connection out->sessionsTotal=0; out->sessionsRunning=0; out->sessionsWaiting=0; out->recentlyCompleted=false; out->lastUpdated=now; strncpy(out->msg, "No Claude connected", sizeof(out->msg)-1); diff --git a/src/xfer.h b/src/xfer.h index 03934f22..f571a85d 100644 --- a/src/xfer.h +++ b/src/xfer.h @@ -97,7 +97,7 @@ inline bool xferCommand(JsonDocument& doc) { } if (strcmp(cmd, "unpair") == 0) { - bleClearBonds(); + bleRemoveCurrentBond(); _xAck("unpair", true); return true; }