Aller au contenu principal
Version: 0.1.0

Modèle de données

Cette page décrit les entités principales que stocke Openbeehive, comment elles sont liées, et comment les scopes déterminent ce qui est synchronisé et avec qui. Elle est rédigée du point de vue de l'approche hors-ligne d'abord : la même structure réside dans la base de données SQLite-WASM de l'appareil et dans la base de données enfichable du serveur, et le protocole de synchronisation les maintient cohérentes.

Si vous voulez comprendre les mécanismes du suivi des changements (horodatages HLC, dernier écrivain gagne, OR-Sets, événements en ajout seul), lisez d'abord Historique et événements — cette page se concentre sur les entités elles-mêmes.

La hiérarchie

Au sommet se trouve le Rucher (Apiary, un emplacement ou un terrain). Chaque rucher contient des Ruches ; chaque ruche possède une Reine actuelle et accumule un flux d'enregistrements au fil du temps.

Apiary
├── Hive ──────── Queen (current; queens form a succession over time)
│ ├── Inspection (a visit: what you saw)
│ ├── Task (something to do, with a due date)
│ ├── Event (append-only fact: requeened, split, died, moved…)
│ ├── Harvest (honey/wax taken off)
│ └── Treatment (varroa or disease treatment applied)

└── Placement (hive ↔ apiary, time-bounded — where a hive lived, and when)

ApiaryShare (apiary ↔ user — grants another beekeeper access via a scope)

Une ruche appartient à un seul rucher à la fois, mais Placement enregistre l'historique complet des emplacements où une ruche a vécu, de sorte qu'une ruche peut se déplacer d'un terrain à l'autre sans perdre ses enregistrements.

Entités et champs clés

Chaque entité partage une enveloppe commune utilisée par la synchronisation : un id stable (un UUID généré hors ligne), un scope_id (voir Scopes), des colonnes de gestion HLC, et un indicateur de suppression douce. Les champs ci-dessous sont ceux qui ont un sens métier.

Apiary

Le conteneur et l'unité de partage.

ChampNotes
idUUID
namepar ex. « Rucher de la maison »
locationtexte libre ou latitude/longitude
notestexte libre
scope_idégale l'id propre du rucher (voir ci-dessous)

Hive

Le logement d'une colonie au sein d'un rucher.

ChampNotes
idUUID ; également encodé dans l'étiquette QR de la ruche
apiary_idrucher actuel (le placement actif)
name / short_codeétiquette lisible et code court imprimé sur le QR
typel'un de Zander, Dadant, Deutsch Normal, Langstroth, Warre, Top-bar, Other — voir Types de ruches
statuspar ex. active, morte, vendue
notestexte libre
scope_idl'id du rucher

Queen

La reine régnante d'une ruche. Les reines forment une succession : lorsqu'une colonie est remérée, la reine précédente est clôturée et un nouvel enregistrement s'ouvre, ce qui permet de conserver la lignée complète.

ChampNotes
idUUID
hive_idla ruche qu'elle dirige
yearannée d'introduction / de naissance
marking_coloursuit le code couleur international (1/6 blanc, 2/7 jaune, 3/8 rouge, 4/9 vert, 5/0 bleu)
originélevée, achetée, essaim, supersédure…
clippedaile coupée (booléen)
scope_idl'id du rucher de sa ruche

Inspection

Une visite datée : l'instantané de ce que vous avez observé.

ChampNotes
id, hive_id, datequi et quand
brood, stores, temperamentobservations typiques
queen_seen, eggs_seen, queen_cellsvérifications rapides
varroa_countchute / comptage de varroas si effectué
temp_hive, temp_outsidetempérature (°C) à l'intérieur de la ruche et à l'extérieur
humidity_hive, humidity_outsidehumidité relative (%) à l'intérieur de la ruche et à l'extérieur
notestexte libre
scope_idl'id du rucher

Les champs climatiques sont de simples scalaires optionnels ; ils sont donc synchronisés champ par champ comme toute autre colonne et peuvent être remplis à la main ou par un capteur automatisé — voir Trackers automatisés.

Task

Quelque chose à faire pour une ruche ou un rucher, avec une date d'échéance et un état d'achèvement.

ChampNotes
idUUID
hive_id / apiary_idle sujet (une tâche peut cibler l'un ou l'autre niveau)
title, due_date, donel'essentiel
scope_idl'id du rucher

Event

Un fait en ajout seul concernant une ruche — remérée, divisée, essaimée, morte, déplacée, nourrie. Les événements ne sont jamais modifiés ni fusionnés ; ils ne font que s'accumuler, ce qui explique qu'ils n'entrent jamais en conflit lors de la synchronisation. Ils constituent l'épine dorsale de la chronologie de la ruche.

ChampNotes
id, hive_id, occurred_atquand cela s'est produit
kindle type d'événement
payloaddétail spécifique au type (JSON)
scope_idl'id du rucher

Voir Historique et événements pour le catalogue complet des événements et la manière dont la chronologie est assemblée.

Harvest

Le miel (ou la cire) récolté sur une ruche.

ChampNotes
id, hive_id, datela récolte
productmiel, cire, propolis…
quantity, unitpar ex. 12.5 kg
notespar ex. miellée, humidité
scope_idl'id du rucher

Treatment

Un traitement contre le varroa ou une maladie appliqué à une ruche.

ChampNotes
id, hive_id, datesujet et date d'application
product, active_ingredientpar ex. Oxuvar / acide oxalique
dose, methodpar ex. 50 ml, dégouttement
batch_numberlot / charge (souvent exigé par la loi)
withdrawal_untildate à laquelle le miel peut à nouveau être récolté sans danger
reasonpar ex. varroa
notetexte libre
apiary_id, queen_idcontexte figé au moment de l'application
scope_idl'id du rucher
remarque

Les règles de traitement et de dosage varient selon le pays et l'homologation du produit. Openbeehive enregistre ce que vous avez fait ; il ne prescrit rien. Respectez toujours vos autorisations locales — voir Varroa.

Placement

Le lien limité dans le temps entre une ruche et un rucher : où une ruche a vécu et pendant combien de temps. Un nouveau placement s'ouvre lorsqu'une ruche se déplace ; le précédent se clôture.

ChampNotes
id, hive_id, apiary_idle lien
from / untilintervalle ; until est null tant que le placement est en cours
scope_idl'id du rucher

ApiaryShare

Accorde à un autre apiculteur l'accès à un rucher (et à tout ce qu'il contient).

ChampNotes
id, apiary_idce qui est partagé
user_idavec qui c'est partagé
rolepar ex. lecteur, éditeur

Scopes et contrôle de la synchronisation

Le partage se fait au niveau du rucher, et une seule valeur le pilote : chaque enregistrement porte un scope_id.

  • Pour les données appartenant à un rucher — ruches, reines, inspections, tâches, événements, récoltes, traitements, placements, et le rucher lui-même — le scope_id est l'id du rucher.
  • Pour les données qui appartiennent à un seul utilisateur et ne sont jamais partagées (par ex. les préférences personnelles), le scope_id prend la forme user:<id>.

Lorsque deux appareils se synchronisent, ils n'échangent que les scopes auxquels l'utilisateur a droit. Le serveur résout l'ensemble des scopes d'un utilisateur ainsi :

scopes(user) = { "user:<their id>" }
∪ { apiary.id for each apiary they own }
∪ { share.apiary_id for each ApiaryShare granting them access }

Ajouter un ApiaryShare fait donc apparaître un rucher entier — chaque ruche et chaque enregistrement qu'il contient — sur les appareils du destinataire lors de la prochaine synchronisation ; le révoquer empêche les changements ultérieurs de circuler. Comme le contrôle repose sur la colonne scope_id, le partage est tout ou rien par rucher et ne nécessite aucune autorisation par enregistrement.

astuce

Un id de ruche à lui seul n'accorde aucun accès. Scanner une étiquette QR ouvre l'application sur une ruche uniquement si le scope de cette ruche a effectivement été synchronisé sur votre appareil.

Pourquoi la fusion se fait proprement

Les structures ci-dessus sont conçues pour que la synchronisation n'ait jamais besoin d'un humain pour résoudre un conflit :

  • Les champs scalaires (la couleur de marquage d'une reine, le nom d'une ruche) utilisent le principe du dernier écrivain gagne, champ par champ, déterminé par les horodatages HLC.
  • Les champs de type liste/ensemble utilisent des OR-Sets « add-wins », de sorte que les ajouts concurrents sont tous conservés.
  • Les événements sont en ajout seul et immuables ; ils s'accumulent donc simplement.

Pour l'algorithme complet, poursuivez avec le protocole de synchronisation.