- Bloquants: mermaid 03-picking/_index reconstitue (archive 11-05), 13 liens vers pages squelette retires, 2 liens recibles (anoxie, application-dictionary) - Conventions: 910 em dashes -> tirets simples, 145 checklists -> puces question, 13 questions resolues barrees - Liens: 9 ancres reparees (slugs GitHub) - Delta: 12 standard_ref remappes, blocs Standard EasyWMS + sections References ajoutes, front matter complete - Glossaire: 15 termes standard deplaces en section rappel avec renvoi - Rapport: limagrain/_lint_report.md (Phase 1 + Phase 2 + re-scan final) - Inclut les pages des sessions precedentes non commitees + CLAUDE.md et consume.log en l'etat
33 KiB
title, tags, status, standard_ref, jira_refs, confluence_refs, sources, last_updated, author
| title | tags | status | standard_ref | jira_refs | confluence_refs | sources | last_updated | author | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Intégration Still iGo - API PACS et architecture |
|
draft | modules/agv.md |
|
|
2026-07-20 | Arthur |
Intégration Still iGo - API PACS et architecture
Résumé : documentation complète de l'intégration du fleet manager iGO easy (STILL / KION Group) avec EasyWMS chez Limagrain. Couvre l'API REST PACS 2.3, le cycle de vie des transports, le mapping avec le module AGV standard, l'architecture cible à 4 composants et les réponses FAQ STILL contractuelles.
Standard EasyWMS : → voir AGV - Automated Guided Vehicles Le standard communique par tables d'échange DB (EAG/AGE/AGS). Chez Limagrain, iGO easy remplace le protocole historique par une API REST HTTPS - un middleware (pool IIS C#) assure la traduction.
Contexte projet
Limagrain utilise des AGV Still EXV CB iGo (gerbeurs électriques automatisés) pour les transports internes entre images de quai, PIE, postes de picking et zones de stockage. Le fleet manager est iGO easy (variante simplifiée de PACS - Productized Automated Concept Solutions), motorisé par le moteur interne E'tricc.
La communication est 100 % REST HTTPS (port 7002, TLS 1.2) - pas
de PLC ni de tables d'échange SQL directes entre WMS et iGO. Le modèle
est pull + push : le WMS pousse les ordres (POST /transports),
iGO pousse les changements d'état via webhook (callback POST vers une
URL exposée par le WMS).
Vue d'ensemble iGO / PACS
flowchart LR
subgraph WMS["Hôte (EasyWMS)"]
EasyWMS["EasyWMS + CstAGV"]
end
subgraph FleetMgr["iGO easy / PACS Fleet Manager"]
Etricc["Moteur E'tricc"]
MyMA["MyMA admin UI"]
Etricc <--> MyMA
end
subgraph Fleet["Flotte AGV"]
EXV["EXV CB iGo<br/>(gerbeur ~3.4m)"]
end
EasyWMS <-->|"HTTPS REST<br/>port 7002<br/>TLS 1.2 + X-API-Key"| Etricc
Etricc -.->|"callback POST<br/>vers WMS"| EasyWMS
Etricc <--> Fleet
Concepts clés :
- Pas de notion de routes/segments côté WMS : iGO ne demande qu'une
sourceLocationet unedestinationLocation- la trajectoire physique est gérée par iGO en interne. - Décision tardive (Group / decision point) : si la destination
exacte est inconnue à la création, on donne un
destinationGroupId. iGO place le transport enRequestDestinationet interroge le WMS quand l'AGV arrive au point de décision. - Load = container EasyWMS - passé directement dans le payload de
création du transport (pas de
POST /api/loadspréalable - FAQ #5).
Stack technique iGO (MyMA)
| Composant | Détail |
|---|---|
| Backend | .NET 8.0 (C#) |
| Frontend | Vue 3.2 |
| Base de données | Postgres 12+ (défaut), SQL Server 2019 ou MySQL 8.0 |
| OS serveur | Windows 11/Server 2016-2022, Ubuntu 18.04 |
| Hardware (low) | 4 cores @2.26 GHz, 8 Go RAM, 500 Go RAID5, dual PSU |
| Hardware (high) | 8 cores, 16 Go RAM, 1 To, dual PSU |
Ports réseau
| Service | Port |
|---|---|
| Front-end admin MyMA | 82 |
| Backend REST interne | 50005 |
| API Host (HTTPS REST) | 7002 |
| Postgres | 5432 |
Véhicule - Still EXV CB iGo
Gerbeur électrique automatisé (EXV = Elektro-Vertikal) - se déplace sur ses propres roues et lève la charge avec le mât. Pas de couloir mécanique ni de canal compact.
| Caractéristique | Valeur |
|---|---|
| Longueur totale (l1) | 3 383 mm |
| Longueur jusqu'au dosseret (l2) | 2 083 mm |
| Largeur tablier fourche | 1 000 / 920 / 1 109 mm |
| Fourche (s / e / l) | 50 / 100 / 1 300 mm |
| Hauteur véhicule (arche / mât) | 2 447 / 2 015 mm |
Modèle de ressources API
L'API PACS 2.3 expose 8 ressources :
| Ressource iGO | Équivalent EasyWMS | Description |
|---|---|---|
| Transport | AgvTask |
L'ordre de transport (le cœur) |
| Vehicle | AGV station (type 65) | Le véhicule physique |
| Load | Container / LPN |
La charge physique |
| LoadType | ContainerType |
Catalogue de types de charge |
| Location | Location (IRealLocation) |
Point physique du warehouse |
| Group | WorkingZone |
Ensemble de locations (décision tardive) |
| System | - | État global + abonnements |
Champs clés du Transport
| Champ iGO | Type | Équivalent EasyWMS |
|---|---|---|
id |
string | (généré par iGO) |
transportHostId |
string | OrderExtId (= Task.TaskNumber) |
sourceLocationId / sourceGroupId |
string | LoadLocation |
destinationLocationId / destinationGroupId |
string | UnloadLocation |
load |
Load | Container (PalletId, type, dimensions) |
priority |
int 0-10 | Priority 0-4 (conversion inversée) |
suspended |
bool | (pas d'équivalent - false par défaut) |
customMetaData |
dict | HasTopper, PalletType, etc. |
status |
enum | AgvStatus (mapping § ci-dessous) |
Champs clés du Vehicle
| Champ | Type | Description |
|---|---|---|
id |
string | Identifiant véhicule |
mode |
enum | Manual / Automatic / SemiAutomatic / Removed / Disabled |
status |
enum | Idle / Executing / Charging / Faulted / Manual |
pose |
object (x, y, orientation) | Position physique temps réel |
batteryLevel |
int | % batterie |
errors |
array | Codes/labels d'erreur |
Inventaire des endpoints API
Tous sur https://[IP]:7002/api/... avec header X-API-Key.
Transports
| Verbe | URL | Effet |
|---|---|---|
| GET | /api/transports |
Liste des transports en mémoire |
| POST | /api/transports |
Créer un transport |
| GET | /api/transports/{id} |
Détail d'un transport |
| POST | /api/transports/{id}/final-destination |
Fixer destination finale (group → location) |
| POST | /api/transports/{id}/final-source |
Fixer source finale (group → location) |
| POST | /api/transports/{id}/suspend |
Mettre en pause |
| POST | /api/transports/{id}/release |
Relancer après suspend |
| POST | /api/transports/{id}/cancel |
Annuler |
| POST | /api/transports/{id}/priority?priority={0-10} |
Changer priorité |
| POST | /api/transports/subscription?callbackUrl=… |
S'abonner aux events transport |
| DELETE | /api/transports/subscription?callbackUrl=… |
Se désabonner |
Vehicles
| Verbe | URL | Effet |
|---|---|---|
| GET | /api/vehicles / /{id} |
Lecture véhicules |
| POST | /api/vehicles/suspend |
Suspendre toute la flotte |
| POST | /api/vehicles/resume |
Relancer toute la flotte |
| POST | /api/vehicles/{id}/suspend / .../resume |
Suspend/resume un AGV |
| POST | /api/vehicles/restart |
Redémarrer la flotte |
| POST | /api/vehicles/subscription?callbackUrl=… |
S'abonner aux events vehicle |
Autres
| Verbe | URL | Effet |
|---|---|---|
| GET | /api/system |
Status global + subscriptions |
| GET | /api/groups / /{id} |
Lecture des groupes |
| GET | /api/loads / /{id} |
Lecture des loads |
| POST | /api/loads |
Créer une load (non recommandé - FAQ #5) |
| GET | /api/locations / /{id} |
Lecture des locations |
| GET | /api/load-types |
Catalogue des types |
Endpoints callback côté WMS (webhook receiver)
| URL côté WMS | Body reçu | Déclenchement |
|---|---|---|
POST /agv/transport-event |
Objet Transport complet | Changement d'état transport |
POST /agv/vehicle-event |
Objet Vehicle complet | Changement d'état véhicule |
Cycle de vie d'un Transport
flowchart TD
Req[Requested] --> Pen[Pending]
Pen --> Asg[Assigned]
Asg -->|source = Group| RS[RequestSource]
Asg -->|source = Location| Ret[Retrieving]
RS -->|final source set| Ret
RS -->|AGV arrivé sans réponse| WS[WaitSource]
WS -->|final source set| Ret
Ret --> Rtd[Retrieved]
Rtd -->|dest = Group| RD[RequestDestination]
Rtd -->|dest = Location| Sto[Storing]
RD -->|final dest set| Sto
RD -->|AGV arrivé sans réponse| WD[WaitDestination]
WD -->|final dest set| Sto
Sto --> Std[Stored]
Std --> Fin[Finished]
Asg -.cancel.-> Can[Cancelled]
Pen -.cancel.-> Can
Ret -.error.-> Abo[Aborted]
Sto -.error.-> Abo
États terminaux : Finished, Cancelled, Aborted.
⚠️ Le statut
Newest un état interne instantané d'iGO - il n'apparaît jamais dans les callbacks. Le premier état observable estRequested(FAQ #4).
Mapping états iGO → phases EasyWMS
| iGO Transport.status | Phase AGV EasyWMS | AgvStatus | Notes |
|---|---|---|---|
| Requested | - | (après POST) | Premier état observable |
| Pending | 100 (Order accepted) | Sent |
En file d'attente iGO |
| Assigned | 103 (Vehicle assigned) | (Sent) | ⚠️ Pas de Vehicle.id dans le payload (FAQ #1) |
| RequestSource | 104 (Load permission) | PendingToBeLoad |
Uniquement en mode Group |
| Retrieving | - | (Sent) | AGV en route / chargement |
| Retrieved | 106 (Load confirmed) | (Sent) | Vehicle.id disponible ici (FAQ #1) |
| RequestDestination | 108 (Unload permission) | PendingToBeUnload |
Uniquement en mode Group |
| Storing | - | - | AGV en dépose |
| Stored / Finished | 110 (Unload confirmed) | (purge) | Transport terminé |
| Cancelled | 255 | (Cancelled) | Annulé |
| Aborted | 255 | (Cancelled) | Erreur irrécupérable - aucun code d'erreur dans le payload (FAQ #2) |
Différence sémantique majeure : CanPick / CanDrop
Le standard EasyWMS attend une demande explicite d'autorisation
(phases 104 / 108) quand CanPick / CanDrop sont à false. iGO ne
demande l'autorisation qu'au point de décision d'un Group. Si la
source/destination est une Location connue dès la création, iGO
exécute directement sans demander d'autorisation.
Pour reproduire le comportement EasyWMS dans iGO, il faut forcer
l'usage de Groups (même mono-location) là où EasyWMS aurait
CanPick = false.
Conversion de priorité
| EasyWMS | iGO | Suggestion |
|---|---|---|
| 0 - Urgent | 10 - Highest | mapping direct |
| 1 - High | 8 | |
| 2 - Normal | 5 | |
| 3 - Low | 3 | |
| 4 - VeryLow | 1 |
Flux nominal - création et exécution
sequenceDiagram
autonumber
participant WMS as EasyWMS
participant iGO as iGO easy
participant V as Vehicle
WMS->>iGO: POST /api/transports
iGO-->>WMS: 200 OK (status=Requested)
iGO->>WMS: callback (Pending)
iGO->>V: assigne véhicule
iGO->>WMS: callback (Assigned)
V->>iGO: arrivé source
iGO->>WMS: callback (Retrieving)
V->>iGO: chargé
iGO->>WMS: callback (Retrieved)
V->>iGO: arrivé destination
iGO->>WMS: callback (Storing)
V->>iGO: déchargé
iGO->>WMS: callback (Stored → Finished)
Flux avec décision tardive (Group)
sequenceDiagram
autonumber
participant WMS
participant iGO
participant V as Vehicle
WMS->>iGO: POST /api/transports {destinationGroupId}
iGO-->>WMS: 200 OK (Requested)
iGO->>WMS: callback (Assigned → Retrieving → Retrieved)
V->>iGO: arrivé au decision point
iGO->>WMS: callback (RequestDestination)
WMS->>iGO: POST /final-destination {destinationId}
iGO-->>WMS: 200 OK
iGO->>WMS: callback (Storing → Stored → Finished)
⚠️ Si le WMS ne répond pas assez vite, iGO bascule de
RequestDestinationversWaitDestination(AGV arrivé et en attente). Symétrique côté source :RequestSource→WaitSource.
Annulation
Un transport ne peut pas être annulé après l'état Retrieved
(FAQ #6). Si un cancel arrive côté WMS après Retrieved, deux
options : attendre Finished puis créer une tâche retour, ou
intervenir manuellement.
Sécurité et abonnements
Authentification
X-API-Key (confirmé par STILL - FAQ #8). Le header
Authorization: Bearer mentionné dans certaines parties de la doc
PACS est obsolète. La clé est fixe, fournie par le PM STILL, stockée
chiffrée dans la config du middleware.
TLS
HTTPS avec TLS 1.2. Certificats auto-signés côté iGO - le WMS doit les truster explicitement (import dans le keystore).
Modèle d'abonnement
Au démarrage du WMS :
POST /api/transports/subscription?callbackUrl=https://wms/agv/events/transportPOST /api/vehicles/subscription?callbackUrl=https://wms/agv/events/vehicle
À l'arrêt : DELETE sur les mêmes URLs. Le endpoint callback doit
être en HTTPS, retourner 200 OK rapidement (< 1s), traitement
asynchrone derrière. Le listener doit être idempotent : clé de
déduplication = transport.id + status (FAQ #9).
Mapping erreurs iGO → EasyWMS
| Code EasyWMS | Famille | Équivalent iGO |
|---|---|---|
| 1001-1014 | Configuration | HTTP 400 BadRequest à la création |
| 2003 | Extraction error | Transport.status = Aborted + Vehicle.errors[] |
| 2004 | Putaway error | idem |
| 2005 | Manual cancel | Transport.status = Cancelled en callback |
| 2500-2503 | Communication | Erreurs HTTP 5xx / timeouts |
| 2700 | Wrong container | Vehicle.errors[] + status = Faulted |
⚠️ Le payload
Abortedne contient aucun code d'erreur (FAQ #2). Pour enrichir leFlagsAGE, il faut faire unGET /api/vehicles/{id}complémentaire pour récupérererrors[].errorCode.
Mapping verbes / opérations
| Action métier | EasyWMS (Operation + EAG) | iGO (REST) |
|---|---|---|
| Créer un ordre | Operation = Create + ligne EAG |
POST /api/transports |
| Modifier un ordre | Operation = Update + ligne EAG |
POST /priority, /final-source, /final-destination |
| Annuler un ordre | Operation = Delete + ligne EAG |
POST /api/transports/{id}/cancel |
| Suspendre un ordre | (pas d'équivalent) | POST /suspend |
| Reprendre un ordre | (pas d'équivalent) | POST /release |
| Suspendre la flotte | (pas d'équivalent) | POST /api/vehicles/suspend |
| Auth load | EAG Update (CanPick=true) |
POST /final-source |
| Auth unload | EAG Update (CanDrop=true) |
POST /final-destination |
Architecture cible - Pattern à 4 composants
Principe directeur
EasyWMS communique avec les fleet managers externes via une base intermédiaire (5 tables). Côté Mecalux, la Gateway AGV (existante) mediate entre les workflows et les tables. Côté flotte, un middleware à développer (pool IIS C# .NET 8) traduit les tables vers/depuis l'API REST PACS.
Le custom CstAGV n'est pas modifié. L'intégration iGO consiste uniquement à fournir le middleware.
flowchart LR
subgraph EasyWMS["EasyWMS (existant)"]
Process[Process<br/>Putaway/Picking/Shipping]
AgvCore[Module AGV core<br/>+ CstAGV]
GwMec[Gateway AGV Mecalux<br/>workflows ↔ tables]
end
subgraph DB["Base intermédiaire"]
OQ[(AGV_OUTPUTQUEUE)]
EAG[(AGV_EAG)]
IQ[(AGV_INPUTQUEUE)]
AGE[(AGV_AGE)]
AGS[(AGV_AGS)]
end
subgraph Pool["Pool IIS C# .NET 8 - À DÉVELOPPER"]
Pump[Pompe sortante<br/>poll OUTPUTQUEUE → API iGO]
Hook[Webhook receiver<br/>callbacks iGO → tables]
end
subgraph KION["iGO / PACS (STILL)"]
iGO[API REST port 7002]
end
Process --> AgvCore --> GwMec
GwMec --> OQ & EAG
GwMec -.poll.-> IQ & AGE & AGS
Pump -.poll.-> OQ
Pump -.lit.-> EAG
Pump -->|HTTPS X-API-Key| iGO
iGO -.webhook.-> Hook
Hook --> IQ & AGE & AGS
Composants existants - RIEN à modifier
| Composant | Rôle | Statut |
|---|---|---|
| CstAGV (workflows) | Logique métier AGV | ✅ Existant |
| Gateway AGV Mecalux | Mediator workflows ↔ tables | ✅ Existant |
| Tables AGV_* (5) | Base intermédiaire | ✅ Existantes |
| Vues SmartUI AGV | Monitoring opérateur | ✅ Existantes |
Middleware pool IIS - seul livrable nouveau
| Aspect | Description |
|---|---|
| Forme | Pool IIS C# ASP.NET Core (.NET 8.0) |
| Hébergement | Serveur Mecalux (co-localisé ou VM séparée) |
| Rôle | Pompe sortante + webhook receiver dans un service unique |
| Accès BDD | Connection vers les 5 tables AGV_* |
| Sécurité | X-API-Key sortant + HTTPS entrant (TLS 1.2) |
Pompe sortante (OUTPUTQUEUE → API iGO)
Polling régulier (1-5 s) sur AGV_OUTPUTQUEUE WHERE processedDate IS NULL ORDER BY creationDate ASC. Pour chaque ligne : récupère
batchId → lit AGV_EAG → interprète l'Operation (C/U/D) → appel
REST iGO. Après ack synchrone (200 OK) : marque processedDate.
Webhook receiver (callbacks → tables)
Controller ASP.NET Core exposant deux endpoints HTTPS. À réception :
insert dans AGV_INPUTQUEUE → insert dans AGV_AGE ou AGV_AGS
avec le mapping Status → EventType/Flags (cf. tableau ci-dessous).
Horodatage DateTime.UtcNow à la réception (iGO ne fournit pas de
timestamp - FAQ #3).
Mapping Status iGO → (EventType, Flags) AGE
| iGO Transport.status | EventType | Flags | Notes |
|---|---|---|---|
| Pending | 100 | 0 | Order accepted |
| Assigned | 103 | 0 | Vehicle assigned - StationNumber=null (FAQ #1) |
| Retrieved | 106 | 0 | Load confirmed - Vehicle.id disponible ici |
| Stored / Finished | 110 | 0 | Unload confirmed |
| Cancelled | 255 | 0 | Annulé |
| Aborted | - | 2003/2004 | À enrichir via GET /api/vehicles/{id} (FAQ #2) |
Pattern de boot du middleware
À chaque démarrage :
- Vérifier la base intermédiaire accessible
- Vérifier l'API iGO :
GET /api/system - Vérifier les subscriptions actives - (re)créer si absentes
- Réconcilier les transports :
GET /api/transportsvsAGV_OUTPUTQUEUEnon acquittées → générer les lignes AGE manquantes - Démarrer le polling sortant
Logique d'annulation côté middleware
À la lecture d'un EAG Operation=Delete, le middleware doit vérifier
le status iGO courant :
- Requested / Pending / Assigned / Retrieving →
POST /cancel✅ - Retrieved / Storing / Stored → ❌ Cancel impossible (FAQ #6) → écrire un Flags d'erreur dans AGE → notification opérateur → fallback (attendre Finished + tâche retour, ou RFT)
- Cancelled / Aborted / Finished → no-op (déjà terminal)
Refus WMS de l'annulation quand le support est sur un AGV (LIM-104)
Statut : préprod ; revue de code validée le 23/06/2026 (Vincent Charvet).
Problème (découvert aux tests STILL) : si on annule / supprime une Task
AGV alors que le support est déjà pris par l'AGV (transport iGO
>= Retrieved), iGO refuse l'annulation et termine physiquement la
mission - mais le WMS a déjà supprimé la Task au moment de la demande.
ProcessEvents_PR s'arrête alors sur sa garde CST Get Task (« CST Task
exists » = false) pour toutes les AGE suivantes :
- l'AGE
255/1009ne déclenche jamaisProcessError1009→ notification opérateur du refus perdue ; - l'AGE
110(Unload confirmed) ne déclenche jamaisContainerMove→ support figé sur l'AGV.
Solution : souscription preview sur la commande de suppression / annulation de Task. Avant exécution :
- récupérer le support (container) associé à la Task ;
- vérifier s'il est sur un AGV - critère retenu
Container.StationType == Agv(équivalent métier de « palette physiquement sur l'AGV » = iGO>= Retrieved; repli possible :LocationCodecommençant parAGV_) ; - si sur AGV → refuser la commande (exception) avec message opérateur explicite. La Task reste vivante, l'AGV termine sa mission, le support est livré à destination ;
- sinon (support encore à la source ou déjà déposé) → laisser la commande s'exécuter normalement.
| Élément AD | Type | Rôle |
|---|---|---|
CST_TaskCancel_CheckAgv |
Subscription | Appelle le WF à l'annulation d'une tâche |
CST_TaskDelete_CheckAgv |
Subscription | Appelle le WF à la suppression d'une tâche |
CST_CancelTask_CheckForAgv |
Workflow | Récupère la tâche annulée / supprimée ; si le conteneur est sur un emplacement AGV, lève une erreur (numéro de tâche + code conteneur) |
CST_CancelTask_NotPossible_2 |
Ressource | FR « Impossible de supprimer la tâche {0} car le conteneur {1} est sur un AGV » / EN « Cannot delete task {0} because container {1} is on AGV » |
Cas de test : (1) annulation après pickup (>= Retrieved) → refusée,
support livré, Task Finished ; (2) annulation avant pickup
(< Retrieved) → acceptée, EAG D, middleware POST cancel iGO 204.
Comparaison avec les Gateways historiques
| Aspect | EasyWMSGateway2015 (Galileo) | GatewayRocla2015 | Pool IIS iGO |
|---|---|---|---|
| Communication aval | TCP socket (port 3000) | TCP socket (port 50011) | HTTPS REST (port 7002) |
| Format messages | Frames GALILEO bas niveau | Frames Rocla propriétaires | JSON REST |
| Auth | TokenUser dans config |
Intégrée au protocole | X-API-Key |
| Architecture | Monolithique | Monolithique (Gateway + middleware fusionnés) | Découplée via tables AGV_* |
| Liaison Mecalux | (autre architecture) | Abonnement direct WF (héritage EasyB) | Tables AGV_* (archi moderne) |
La pool IIS iGO ne doit pas être un fork de GatewayRocla2015 (ancienne architecture monolithique). Développement from scratch sur ASP.NET Core .NET 8 recommandé.
Workflows EasyWMS - impact iGO
Avec le pattern Gateway iGO + tables AGV_*, aucun workflow EasyWMS ni la Gateway AGV Mecalux n'a besoin d'être modifié. La spécificité iGO est entièrement encapsulée dans le middleware.
⚠️ Réserve (LIM-103, préprod) : ce tableau reflète l'hypothèse de conception. À l'implémentation, plusieurs bugs du module AGV standard Mecalux ont dû être corrigés (dispatch d'events cassé par la transformation Gateway
phase + 100, attributscanPick/canDropjamais assignés, events 106/110 non gérés, refus de mission iGo). Détail : Corrections des bugs du module AGV standard (LIM-103).
| Workflow | Comportement avec Gateway iGO |
|---|---|
MovementCreatedEventHandler_PR |
✅ Inchangé - déclencheur |
AgvTask_CreateTaskFromMovement_PR |
✅ Inchangé |
SerializeAgvTasks_PR |
✅ Inchangé - écrit EAG, le middleware lit et POST |
ProcessEvents_PR + ProcessEvent_*_PR |
⚠️ Modifié (LIM-103) - patch dispatch phase+100, gestion events 106/110, refus mission, fix canPick/canDrop |
ProcessErrors_PR |
✅ Inchangé - réagit aux Flags dans AGE |
Agvtask_CanPick/CanDrop_PendingToBeSent_PR |
✅ Inchangé - écrit EAG, le middleware appelle /final-source ou /final-destination |
TaskCanceledEventHandler_PR |
✅ Inchangé - écrit EAG Delete, le middleware gère |
| Workflows RFT | ✅ Inchangés - fallback préservé |
Corrections des bugs du module AGV standard (LIM-103)
Statut : préprod ; revue de code à faire (@Vincent, 30/06/2026), assignée Vincent Charvet. Ticket regroupant les corrections nécessaires pour faire fonctionner le module AGV standard sur ce projet.
Queries standard corrigées
Equipment_AgvTask_GetTask_ByWorkingZone_UI: correction d'une null exception sur query standard.Equipment_AgvTask_LoadEquipment_UI: correction d'un paramètre erroné sur query standard.
Dispatch d'events cassé par la transformation Gateway phase + 100
Bug de cohérence Mecalux entre la Gateway et le module AGV. Le record
agvEvent reçu par ProcessEvents_PR est un GalileoEventCreatedWF dont
le champ EventType (Integer) porte la valeur SIMO de la Gateway,
alors que la DecisionActivity « Event type » de ProcessEvents_PR dispatche
sur les valeurs natives 100 / 103 / 104 / 108.
Chaîne du bug :
- le middleware écrit
phase = 104dansagv_age.phase; - la Gateway lit la ligne et pose
EventType = phase + 100 = 204(avecExtension[PHASE] = 104) ; ProcessEvents_PRreçoitEventType = 204≠ 100/103/104/108 → default silencieux → workflow Completed sans side-effect (silent fail).
Fix : patch de l'activité « Check parameters » de ProcessEvents_PR
(soustraction de 100 pour retrouver la valeur native).
canPick / canDrop jamais assignés (LoadPermission / UnloadPermission)
Bug majeur du standard : dans ProcessEvent_LoadPermission_PR, l'attribut
interne canPick (InitialValue vide) n'est jamais assigné. La
DecisionActivity « Can pick? » prend donc toujours la branche Otherwise No
→ End, et le sous-workflow Agvtask_CanPick_PendingToBeSent_PR (qui pose
CanPick = true) n'est jamais appelé. Même défaut dans
ProcessEvent_UnloadPermission_PR (attribut canDrop).
| Workflow | État | Logique |
|---|---|---|
ProcessEvents_PR |
OK (après patch -100) | Dispatch sur EventType == 100/103/104/108 |
Agvtask_CanPick_PendingToBeSent_PR |
OK | CanPick = true hardcodé, fait le flip |
SetAgvStatus_PR |
OK | if CanPick && CanDrop → Sent ; elif CanPick → PendingToBeUnload ; else → PendingToBeLoad |
ProcessEvent_LoadPermission_PR / ProcessEvent_UnloadPermission_PR |
BUGGÉ | canPick / canDrop jamais assigné → branche No systématique |
Fix : remplacer l'expression de la condition Yes de la DecisionActivity
par !agvTask.CanPick (resp. !agvTask.CanDrop), qui teste directement la
propriété de l'AgvTask récupérée par « Get AGV task ». En l'état, le
standard Mecalux est inutilisable pour le flow LoadPermission /
UnloadPermission.
Events 106 / 110 non gérés (fix temporaire)
Le standard ne gère pas les events 106 (déplacer le support sur l'AGV)
et 110 (déplacer le support de l'AGV vers son emplacement de
destination). Fix temporaire (Michael Chaudier, 29/05) : ProcessEvents_PR
gère désormais les events 106 (confirmation load) et 110 (confirmation
unload), avec ajout des commandes de déplacement du support - chargement
sur l'AGV à l'event 106, déchargement à la destination de la tâche à
l'event 110.
Refus de mission iGo
Ajout (Arthur, 01/06) d'une condition dans ProcessEvents_PR pour gérer le
refus de mission par iGo → annulation de la tâche AGV ; la transition
« sequence 0 » est modifiée pour ne pas catcher cette erreur (non gérée par
le sous-workflow) tant qu'aucun flag d'erreur n'est levé.
Génération du mouvement PS → position PK
Container_MovedEventHandler_PS_PR modifié (Vincent, 02/06, commit
9fa84a83e2)
pour générer le mouvement des PS vers la bonne position du PK (première
position libre). Logique conservée pour la recertification et
l'échantillonnage.
Ce même handler est ensuite spécialisé : redirection selon le type de tâche au picking (voir Placement PS → PK, LIM-82) et placement à la position X max de l'image de quai à l'expédition (voir Assignation automatique de l'image de quai, LIM-94). LIM-103 en pose la base (première position libre).
FAQ STILL - réponses contractuelles
Réponses obtenues de STILL en avril 2026. Valeur contractuelle.
| # | Question | Réponse | Impact |
|---|---|---|---|
| 1 | Vehicle.id dès Assigned ? | Non, seulement à partir de Retrieved |
Insérer StationNumber dans AGE uniquement à partir de Retrieved |
| 2 | Code d'erreur dans payload Aborted ? | Non, juste le statut | Enrichir via GET /api/vehicles/{id} (errors[]) |
| 3 | Timestamp dans callbacks ? | Non | Horodater à la réception (DateTime.UtcNow) |
| 4 | Statut New vs Requested ? | New = interne instantané, traiter Requested comme premier état |
Ignorer New |
| 5 | Créer la Load avant le Transport ? | Non, passer les infos dans le transport | Ne PAS appeler POST /api/loads |
| 6 | Annulation après Retrieved ? | Non | Vérifier status iGO avant cancel |
| 7 | Cas d'usage de suspended ? | Pré-création transport avant dispo palette | suspended = false par défaut |
| 8 | X-API-Key vs Bearer ? | X-API-Key | Jamais Bearer |
| 9 | Retry webhook en cas d'indispo ? | Oui, mais fréquence inconnue | Listener idempotent (transport.id + status) |
| 10 | Persistance après reboot iGO ? | Oui | Boot : vérifier subscriptions + réconcilier via GET /transports |
| 11 | Communication directe ou via iGo Flow ? | Directe avec l'API PACS | Pas de couche iGo Flow |
Points encore ouverts avec STILL
| # | Sujet | Statut |
|---|---|---|
| 3b | Fréquence des vehicle/event (pose updates) | ❌ Ouvert |
| 5b | customMetaData (taille, caractères, ré-émis ?) | ❌ Ouvert |
| 6b | Création/modification de Location via API | ❌ Ouvert (API GET only) |
| 7b | Pallet Shuttle (LoadType = 1) | ❌ Ouvert |
| 8b | Multi-warehouse | ❌ Ouvert |
| 9b | HasTopper (attribut véhicule) | ❌ Ouvert |
Points d'attention
⚠️ CanPick/CanDrop : pour reproduire le standard EasyWMS, forcer l'usage de Groups même mono-location.
⚠️ Priorité inversée : EasyWMS 0=Urgent, iGO 10=Max - conversion à coder dans le middleware.
⚠️ Pas de routing exposé : iGO gère ses routes en interne - pas d'équivalent à "Routes between stations" en EasyS, pas d'erreur "Disabled route" côté iGO.
⚠️ Annulation après chargement impossible : la logique
AgvTask_SetCancelledTask_PR qui déclenche la recherche de relocation
après chargement n'a plus de sens dans le mapping iGO. Le WMS refuse
désormais l'annulation en amont via la souscription preview LIM-104 (voir
Refus WMS de l'annulation…).
⚠️ Tests de charge webhook à mener : simuler Gateway iGO down pendant 30s / 1min / 5min pour observer le comportement réel d'iGO (retries, intervalles, abandon).
Capacités nouvelles iGO (hors standard EasyWMS)
- Suspend / Resume / Restart d'une flotte ou d'un véhicule individuel
- Pose temps réel (x, y, orientation) → dashboard live possible
- Battery level → seuils de notification possibles
Questions ouvertes
- ❓ Fréquence des callbacks
vehicle/eventpour les mises à jour de position - risque de flood (@Nicolas) - ❓ Taille max et caractères autorisés dans
customMetaData(@STILL) - ❓ Les
customMetaDatasont-elles ré-émises dans les callbacks transport ? (@STILL) - ❓ Création/modification de Location via API iGO - limité à GET pour l'instant (@STILL)
- ❓ Gestion Pallet Shuttle via iGO (LoadType = 1) - hors scope actuel ? (@Théo)
- ❓ Multi-warehouse : iGO suppose un seul site - impact si extension future ? (@Michael)
Historique des modifications
| Date | Auteur | Modification |
|---|---|---|
| 2026-05-12 | Arthur | Création initiale depuis CR technique iGO STILL |
| 2026-07-20 | Arthur | Intégration LIM-103 (corrections bugs module AGV standard, préprod, revue de code à faire) : nouvelle section (2 queries standard corrigées, dispatch d'events cassé par phase+100, canPick/canDrop jamais assignés dans LoadPermission/UnloadPermission, events 106/110 non gérés, refus de mission iGo, Container_MovedEventHandler_PS_PR première position libre) ; réserve ajoutée sur le tableau « workflows inchangés » (ligne ProcessEvents_PR = Modifié) ; front matter jira_refs/sources/last_updated |
| 2026-07-20 | Arthur | Intégration LIM-104 (refus WMS annulation/suppression Task si support sur AGV, préprod, revue validée 23/06) : sous-section sous « Logique d'annulation » (désync task supprimée avant refus iGo, souscription preview, critère Container.StationType == Agv, table AD CST_TaskCancel_CheckAgv/CST_TaskDelete_CheckAgv/CST_CancelTask_CheckForAgv/CST_CancelTask_NotPossible_2, cas de test) ; cross-ref depuis le point d'attention « Annulation après chargement impossible » ; jira_refs +LIM-104 |
Références
| Source | Type | Date |
|---|---|---|
| CR technique iGO STILL - fonctionnement et flux API v1 | CR technique | 2026-04-28 |
| LIM-103 | Ticket Jira (corrections bugs module AGV standard - préprod, revue à faire, commit 9fa84a83e2) |
2026 |
| LIM-104 | Ticket Jira (refus annulation Task si support sur AGV - préprod, revue validée 23/06) | 2026 |
| 2510_PACS-2.3-Host-Interface-Technical-Specifications | Spec API STILL | 2025-10 |
| iGo easy 2.3 - Host Interface Specifications | Spec API STILL | 2025 |
| IT requirements R1 20250929 | Spec infra STILL | 2025-09-29 |
| Technical specification EXV CB iGo | Datasheet véhicule | 2025 |