Public Access
The Pikachus of the Clock page are icons
Stored as icons at boot from the firmware's bitmaps (cut to 80 x 19), so they can be edited; the firmware copies stay the fallback. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
51b8d87e86
commit
839e86e8f1
17 files changed
+68
-6
No files matched your search
@@ -423,6 +423,8 @@ const char *appBitmapToIcon(const char *name)
|
||||
|
||||
const char *appIconToBitmap(const char *name)
|
||||
{
|
||||
if (builtinIconName(name))
|
||||
return "Built-in icons stay icons (the firmware has them as icons)";
|
||||
Icon icon;
|
||||
if (!loadIcon(name, icon))
|
||||
return "Icon not found";
|
||||
|
||||
+1
-1
@@ -118,7 +118,7 @@ const uint32_t SETUP_AP_DELAY = 20000; // open the AP when WiFi fails thi
|
||||
const uint32_t WIFI_CONNECT_TIMEOUT = 30000;
|
||||
const uint32_t WIFI_RESTART_TIME = 10UL * 60 * 1000;
|
||||
|
||||
#define FIRMWARE_VERSION "2.11.0"
|
||||
#define FIRMWARE_VERSION "2.12.0"
|
||||
|
||||
// Home Assistant device id (do not change: Home Assistant's entities are linked to it)
|
||||
const uint8_t HA_DEVICE_ID[] = {0x34, 0x86, 0x5d, 0x3a, 0x08, 0x28};
|
||||
|
||||
@@ -16,8 +16,7 @@ struct BuiltinBitmap
|
||||
|
||||
static const BuiltinBitmap BUILTIN[] = {
|
||||
{"Nintendo", nintendo_bitmap_Nintendo_new},
|
||||
{"Pikachu", pikachu_clock_bitmap},
|
||||
{"Pikachu yawning", pikachu_yawning_clock_bitmap},
|
||||
// The Pikachus of the Clock page are icons (display/icon_store)
|
||||
};
|
||||
|
||||
static bool mounted = false;
|
||||
|
||||
@@ -6,11 +6,45 @@
|
||||
#include <strings.h>
|
||||
|
||||
#include "display/bitmap_store.h"
|
||||
#include "display/bitmaps.h"
|
||||
|
||||
static const char *DIR = "/icons";
|
||||
// Written when the bitmaps were moved (not a valid name, so never listed)
|
||||
static const char *MIGRATED = "/icons/.migrated";
|
||||
|
||||
// Built into the firmware (full screen bitmaps, cut to icons): stored at boot so they can
|
||||
// be edited, and the fallback when they are not stored
|
||||
struct BuiltinIcon
|
||||
{
|
||||
const char *name;
|
||||
const uint8_t *bitmap; // PROGMEM, BITMAP_BYTES
|
||||
};
|
||||
static const BuiltinIcon BUILTIN[] = {
|
||||
{"Pikachu", pikachu_clock_bitmap},
|
||||
{"Pikachu yawning", pikachu_yawning_clock_bitmap},
|
||||
};
|
||||
|
||||
static bool builtinIcon(const char *name, Icon &icon)
|
||||
{
|
||||
for (const BuiltinIcon &b : BUILTIN)
|
||||
if (strcasecmp(b.name, name) == 0)
|
||||
{
|
||||
uint8_t bitmap[BITMAP_BYTES];
|
||||
memcpy_P(bitmap, b.bitmap, BITMAP_BYTES);
|
||||
iconFromBitmap(bitmap, icon);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool builtinIconName(const char *name)
|
||||
{
|
||||
for (const BuiltinIcon &b : BUILTIN)
|
||||
if (strcasecmp(b.name, name) == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint32_t revision = 0;
|
||||
// Counted once (listing the directory is slow), then kept up to date; -1: not yet
|
||||
static int count = -1;
|
||||
@@ -37,9 +71,24 @@ static bool ensureDir()
|
||||
return LittleFS.exists(DIR) || LittleFS.mkdir(DIR);
|
||||
}
|
||||
|
||||
void iconStoreBegin()
|
||||
{
|
||||
for (const BuiltinIcon &b : BUILTIN)
|
||||
{
|
||||
Icon icon;
|
||||
if (!bitmapStorageAvailable() || LittleFS.exists(path(b.name)) || !builtinIcon(b.name, icon))
|
||||
continue;
|
||||
const char *error = saveIcon(b.name, icon);
|
||||
Serial.printf("Icon \"%s\" stored from the firmware: %s\n", b.name, error ? error : "ok");
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<String> listIcons()
|
||||
{
|
||||
std::vector<String> names = storedNames(DIR, ".bin");
|
||||
for (const BuiltinIcon &b : BUILTIN) // not stored (no storage)
|
||||
if (std::none_of(names.begin(), names.end(), [&b](const String &n) { return strcasecmp(n.c_str(), b.name) == 0; }))
|
||||
names.push_back(b.name);
|
||||
std::sort(names.begin(), names.end(),
|
||||
[](const String &a, const String &b) { return strcasecmp(a.c_str(), b.c_str()) < 0; });
|
||||
return names;
|
||||
@@ -59,7 +108,7 @@ bool iconExists(const char *name)
|
||||
bool loadIcon(const char *name, Icon &icon)
|
||||
{
|
||||
if (!bitmapStorageAvailable() || !validBitmapName(name))
|
||||
return false;
|
||||
return builtinIcon(name, icon);
|
||||
auto cached = cache.find(name);
|
||||
if (cached != cache.end())
|
||||
{
|
||||
@@ -88,6 +137,8 @@ bool loadIcon(const char *name, Icon &icon)
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
if (!ok)
|
||||
ok = builtinIcon(name, loaded);
|
||||
if (cache.size() >= CACHE_MAX)
|
||||
cache.clear();
|
||||
CachedIcon &entry = cache[name];
|
||||
|
||||
@@ -12,6 +12,12 @@
|
||||
|
||||
const int MAX_ICONS = 200;
|
||||
|
||||
// At boot: stores the icons built into the firmware (the Pikachus of the Clock page) when
|
||||
// they are not stored, so they can be edited. The built-in ones stay the fallback.
|
||||
void iconStoreBegin();
|
||||
// One of them (it always exists)
|
||||
bool builtinIconName(const char *name);
|
||||
|
||||
// Sorted without case
|
||||
std::vector<String> listIcons();
|
||||
// Changes each time an icon is saved or deleted
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "app.h"
|
||||
#include "config.h"
|
||||
#include "display/bitmap_store.h"
|
||||
#include "display/icon_store.h"
|
||||
#include "display/page_store.h"
|
||||
#include "logic/status_led.h"
|
||||
#include "nano_link/nano_flash_bridge.h"
|
||||
@@ -34,6 +35,7 @@ void setup()
|
||||
BootMode boot_mode = firmwareGuardBegin();
|
||||
|
||||
bitmapStoreBegin();
|
||||
iconStoreBegin(); // the Pikachus as icons that can be edited
|
||||
pageStoreBegin(); // the Clock page as a page that can be edited
|
||||
appLoadSettings();
|
||||
|
||||
|
||||
Reference in new issue
Block a user