www.safezone-fpv.com

Station S - GeoMail · Extraits

Complément de la page concepts GeoMail : aperçu de l'implémentation (files offline, alias, confirmations). Nous montrons les briques principales sans publier l'intégralité du dépôt.

1. Où vit le code ?

assets/station_s/
+- include/app/ui/geomail/
¦  +- obb_geomail_threads.h      ? structures & API de file
+- src/app/ui/geomail/
   +- obb_geomail_threads.cpp    ? logique FIFO + confirmations

Les handlers réseau/storage restent dans d'autres modules privés ; on expose ici la partie UI/queue.

Schéma futur du circuit GeoMail

Placeholder : un futur schéma montrera comment les messages passent de la file à LVGL.

2. File GeoMail locale

La file conserve les messages normalisés (texte + hash d'image). Extrait :

struct GeoMailMessage {
  std::string mailbox;       // Mairie, Home, Proxy1...
  std::string human_id;      // CVCV-123456
  std::string alias;         // prenom.nom.diff@...
  std::string pseudo;        // affiché côté UI
  std::string subject;
  std::string subject_long;  // champ signé blockchain
  std::string body_preview;
  std::string body_full;
  std::vector<GeoAttachment> attachments;
  uint32_t attachment_hash = 0;
  uint32_t timestamp = 0;
  uint8_t priority = 0;
  uint8_t hop_count = 0;
  bool requires_ack = false;
};

On transporte désormais la boîte source, les champs sujet long, le corps complet (si présent) et la liste de pièces jointes.

3. Limite & purge douce

void enqueue_message(const GeoMailMessage &msg) {
  if (s_pending.size() >= kMaxBuffer) {
    s_pending.pop_front();      // ancien message envoyé vers microSD
  }
  s_pending.push_back(msg);
}

Le buffer reste court (32 éléments) pour garantir une lecture fluide sur écran 3.5?. Le stockage long terme vit sur microSD.

4. Ce que voit l'utilisateur

std::vector<GeoMailMessage> snapshot_queue(std::size_t limit) {
  std::vector<GeoMailMessage> out;
  out.reserve(std::min(limit, s_pending.size()));
  for (const auto &msg : s_pending) {
    out.push_back(msg);
    if (out.size() >= limit) break;
  }
  return out;
}

Cette fonction alimente la vue LVGL (lecture offline, priorité aux urgences) citée dans la section « Travaux en cours ».

5. Accusés (P0/P1)

void mark_acknowledged(uint32_t timestamp) {
  s_pending.erase(std::remove_if(s_pending.begin(), s_pending.end(),
                                 [&](const GeoMailMessage &msg) {
                                   return msg.timestamp == timestamp;
                                 }),
                  s_pending.end());
}

Une fois le message poussé sur la station H/K (ou signé par le maire), on supprime l'entrée locale - exactement ce que promet la page concept.

6. En-tête + machine détat UI

struct GeoMailHeader {
  std::string pseudo;
  std::string obid;          // complet
  std::string obid_short;    // 4 derniers pour la liste
  std::string subject_long;  // signé dans la blockchain
  uint32_t timestamp;
  uint8_t priority;          // 0..3
  uint8_t hop_count;
};

enum class GeoMailView {
  MAILBOX_SELECTION,
  HEADER_LIST,
  READING,
  WRITING
};

La tuile 4 ne fait que passer dun état à lautre : icônes ? liste ? lecture ? écriture. Le header sélectionné reste « docké » en haut de lécran (2 lignes) pendant la lecture ou la rédaction.

7. Contacts avec pseudos et IDs

struct GeoContact {
  std::string pseudo;
  std::string obid;
  std::vector<std::string> aliases;   // prenom.nom.diff
  std::vector<std::string> capabilities; // MAY, POL, ...
};

void add_contact(const GeoContact &contact) {
  s_contacts[contact.obid] = contact;
}

Les pseudos sont libres, mais lID officialise la fiche. Reply/Forward coche simplement plusieurs GeoContact et récupère leurs OBID pour lenveloppe.

8. Pièces jointes non chiffrées

struct GeoAttachment {
  std::string name;
  uint32_t size_bytes;
  std::string tag;
  std::string source_mailbox;  // mairie, proxy1...
};

bool move_to_device(const GeoAttachment &att) {
  return geo_storage_copy(att, kDeviceInboxPath);
}

Pas de popup de destination : on copie directement vers le dossier prévu durant le setup (kDeviceInboxPath). Le regroupement par mail/contact/type/#tag nest quun filtre sur ce tableau.