Files
2026-05-20 09:41:27 +02:00

16 KiB

title, type, sources, related, last_compiled
title type sources related last_compiled
AGV Module — Installation Guide operation
sources/archives/Documentation Module AGV.md
sources/archives/Présentation Module AGV.md
modules/agv.md
concepts/stations.md
2026-05-15

AGV Module — Installation Guide

Overview

This guide covers the end-to-end installation of the AGV module for Easy WMS. The module relies on a PostgreSQL intermediary database, an ODBC driver, an Oracle DBLink (dg4odbc), the Gateway AGV Windows service, and the AGV application package deployed into Easy WMS. For the functional description of the module, see AGV — Automated Guided Vehicles.

Prerequisites

Element Requirement
Easy WMS binaries Version 18.10.22154.1 minimum
PostgreSQL Version >= 14 (note: PostgreSQL 18+ defaults to port 5433)
PostgreSQL ODBC driver psqlodbc x64
Oracle Know the exact ORACLE_HOME path on the VM
Oracle permissions The db_read user must be able to create database links
Firewall PostgreSQL port open (5432 default, 5433 if PostgreSQL 18+)

To find the Oracle version and ORACLE_HOME path:

dir C:\Mecalux\Motor\oracle\Product\

Throughout this guide, [ORACLE_HOME] refers to the full path, e.g. C:\Mecalux\Motor\oracle\Product\19.27.0.0\dbhome_1. Always replace [ORACLE_HOME] with your actual path - leaving the placeholder is a frequent cause of failure.

Step 1 — Install PostgreSQL

Download PostgreSQL >= 14 from the official EDB site and install with default options. Note the listening port - this is critical: PostgreSQL <= 17 uses port 5432, while PostgreSQL 18+ defaults to port 5433.

Create the AGV user and database

In PgAdmin4, create a login role mecaluxAGV (password: mecaluxAGV or per your convention, with login privilege), then create a database named AGV owned by mecaluxAGV.

Allow external connections

Edit C:\Program Files\PostgreSQL\[version]\data\pg_hba.conf and add:

# Allow all IPv4 connections (dev environment only)
host    all    all    0.0.0.0/0    md5

# Alternative: filter by IP range
host    all    all    192.168.0.0/16    md5

Open the firewall port

netsh advfirewall firewall add rule name="PostgreSQL AGV" dir=in action=allow protocol=tcp localport=5432

Adjust the port number if using PostgreSQL 18+ (5433).

Step 2 — Install the PostgreSQL ODBC driver

The download link in the official MSS documentation is dead. Go to the PostgreSQL ODBC releases page and download the latest psqlodbc_x64.msi (not the wrapper setup.exe).

Install the MSI with default options.

Step 3 — Configure the System DSN (64-bit ODBC)

Open ODBC Data Sources (64-bit) (C:\Windows\System32\odbcad32.exe), go to the System DSN tab (not User DSN), click Add, and select the PostgreSQL Unicode(x64) driver.

Field Value
Data Source PostgreSQL35W
Database AGV
Server localhost (or PostgreSQL server IP)
Port 5432 (or 5433 if PostgreSQL 18+)
User Name mecaluxAGV
Password mecaluxAGV

In the Datasource tab, uncheck "Bools as Char". Click Test to verify the connection.

Critical — DSN name case: the name PostgreSQL35W (capital P and W) is used verbatim in 5 different Oracle configuration files. The case must be absolutely consistent across all files. Using POSTGRESQL35W (all caps) or postgresql35w (all lowercase) will cause a silent dg4odbc failure. See the Troubleshooting section for details.

Step 4 — Install and start the Gateway AGV

4.1 — Verify the configuration file

The config file is located at C:\ProgramData\Mecalux\EasyWMS GatewayAGV 2015\. The XML file must contain exactly one <AGVConfig> section. If it contains two (e.g., for two stations), the provider will not initialize and the service will crash with Migration DataBase Provider No Initialized.

Verify that the connection string points to the correct PostgreSQL database:

<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="AGVConfig"
      type="Mecalux.ITSW.AGVGateway.Config.ConfigSettings,
            Mecalux.ITSW.AGVGateway.Config" />
  </configSections>
  <AGVConfig
    connectionString="Host=localhost;user id=mecaluxAGV;password=mecaluxAGV;
                      database=AGV;MaxPoolSize=1000"
    inputCycleDelay="1000"
    outputCycleDelay="1000"
    timeoutCommand="6000"
    providerName="Npgsql"
    stationType="65"
    stationNumber="1"
    warehouseNumber="20000"
    commitLimit="100"
    hoursToExecute="24"
    daysToSave="5">
  </AGVConfig>
</configuration>

If using PostgreSQL 18+ (port 5433), add the port explicitly: Host=localhost;Port=5433;user id=mecaluxAGV;...

4.2 — First startup (table creation)

Start the Gateway AGV service (services.msc > EasyWMS GatewayAGV). Check the log at C:\ProgramData\Mecalux\EasyWMS GatewayAGV 2015\Logs\AllLog.log for successful migration lines:

[Info] [Migration] [Apply] End applying migration: Migration0
[Info] [Migration] [Apply] End applying migration: AgvMigration3

If these lines appear, the tables were created successfully. Errors after these lines are normal (the Gateway tries to communicate with the fleet manager which is not yet connected). Stop the service after verification.

4.3 — Verify created tables

In PgAdmin4, under the AGV database > Schemas > public > Tables, there should be 7 tables: agv_age, agv_ags, agv_eag, agv_inputqueue, agv_maintenance, agv_outputqueue, std_migrationinfo. And 6 sequences: agv_age_id_seq, agv_ags_id_seq, agv_eag_id_seq, agv_inputqueue_id_seq, agv_maintenance_id_seq, agv_outputqueue_id_seq.

4.4 — Execute PostgreSQL scripts

Open the Query Tool in PgAdmin4 on the AGV database and execute:

Script 1 — Notification function (publishes an event on every row change):

CREATE FUNCTION public."NotifyOnDataChange"()
RETURNS trigger LANGUAGE 'plpgsql'
AS $BODY$
DECLARE
  data JSON;
  notification JSON;
BEGIN
  IF (TG_OP = 'DELETE') THEN
    data = row_to_json(OLD);
  ELSE
    data = row_to_json(NEW);
  END IF;
  notification = json_build_object(
    'table', TG_TABLE_NAME,
    'action', TG_OP,
    'data', data);
  PERFORM pg_notify('datachange', notification::TEXT);
  RETURN NEW;
END
$BODY$;

Script 2 — Trigger on the inputqueue table:

CREATE TRIGGER "OnDataChange"
AFTER INSERT ON public.agv_inputqueue
FOR EACH ROW
EXECUTE PROCEDURE public."NotifyOnDataChange"();

Step 5 — Configure the external PostgreSQL user

This user will be used by the Oracle DBLink to access the AGV tables from the WMS.

5.1 — Create the user

In PgAdmin4: create a login role externalAGV with a password and login privilege.

5.2 — Grant CONNECT on the database

In the AGV database properties > Security tab, add externalAGV with the CONNECT privilege.

5.3 — Grant permissions on tables and sequences

Quick option (dev environment):

GRANT ALL ON ALL TABLES IN SCHEMA public TO "externalAGV";
GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO "externalAGV";

Restrictive option (production) - minimum required permissions:

-- Tables
GRANT SELECT, INSERT, UPDATE ON agv_inputqueue TO "externalAGV";
GRANT SELECT, INSERT, UPDATE ON agv_ags TO "externalAGV";
GRANT SELECT, INSERT, UPDATE ON agv_age TO "externalAGV";
GRANT SELECT, UPDATE ON agv_outputqueue TO "externalAGV";
GRANT SELECT ON agv_eag TO "externalAGV";

-- Sequences
GRANT ALL ON agv_age_id_seq TO "externalAGV";
GRANT ALL ON agv_ags_id_seq TO "externalAGV";
GRANT ALL ON agv_inputqueue_id_seq TO "externalAGV";

This is the most delicate step. Oracle uses the dg4odbc component (Database Gateway for ODBC) to connect to PostgreSQL via the ODBC DSN created in Step 3. The configuration touches 3 Oracle files and requires a Listener restart.

6.1 — Edit tnsnames.ora

File: [ORACLE_HOME]\network\admin\tnsnames.ora

Add the following entry at the end of the file. The identifier PostgreSQL35W must start at column 1 (no leading space or tab), otherwise Oracle will not recognize it as a valid TNS entry:

PostgreSQL35W =
  (DESCRIPTION=
    (ADDRESS=(PROTOCOL=tcp)(HOST=localhost)(PORT=1521))
    (CONNECT_DATA=(SID=PostgreSQL35W))
    (HS=OK)
  )

Leave a blank line between the previous entry and this one. (HS=OK) is mandatory - it tells Oracle this is a Heterogeneous Service (connection to a non-Oracle system).

Common error: if the identifier is indented (space or tab before PostgreSQL35W =), Oracle returns ORA-12154: TNS:could not resolve the connect identifier specified. This is a subtle trap because the rest of the file works fine with indentation.

6.2 — Edit listener.ora

File: [ORACLE_HOME]\network\admin\listener.ora

Add a SID_DESC block in the existing SID_LIST_LISTENER section:

(SID_DESC =
  (SID_NAME = PostgreSQL35W)
  (ORACLE_HOME = C:\Mecalux\Motor\oracle\Product\19.27.0.0\dbhome_1)
  (PROGRAM = dg4odbc)
)

Critical: the ORACLE_HOME path in this block must be the real, complete path of your Oracle installation. Never leave a placeholder like [VERSION] - this causes TNS-12518 / ORA-28545 errors. The listener starts without error and the SID appears in lsnrctl status, making the problem hard to diagnose. Verify that the ORACLE_HOME in the PostgreSQL35W block is identical to the other SID_DESC blocks in the file.

6.3 — Create initPostgreSQL35W.ora

Go to [ORACLE_HOME]\hs\admin\, duplicate the file initdg4odbc.ora, rename the copy to initPostgreSQL35W.ora (name must match the SID_NAME exactly, case-sensitive), and replace all content with:

HS_FDS_CONNECT_INFO = PostgreSQL35W
HS_FDS_TRACE_LEVEL = 0

Do not leave the template lines from the original file. For debugging, temporarily set HS_FDS_TRACE_LEVEL = 4 for detailed dg4odbc traces. Reset to 0 after diagnosis.

6.4 — Restart the Oracle Listener

lsnrctl stop
lsnrctl start

Verify that the SID PostgreSQL35W appears in the service list:

lsnrctl status

Expected output: Service "PostgreSQL35W" has 1 instance(s). Instance "PostgreSQL35W", status UNKNOWN, has 1 handler(s) for this service... The UNKNOWN status is normal for a Heterogeneous Service - the process is launched on demand.

Connect as sysdba and grant:

GRANT CREATE DATABASE LINK TO db_read;

The target user is db_read (the Easy WMS read model schema). The database link and synonyms must be owned by db_read. Do not create the link under SYS - it will not be visible from db_read.

Connect as db_read (not sysdba):

CREATE DATABASE LINK AGV
  CONNECT TO "externalAGV" IDENTIFIED BY "mecalux"
  USING 'PostgreSQL35W';

Double quotes around the user and password are mandatory. Oracle converts identifiers to uppercase by default, but PostgreSQL is case-sensitive. Without quotes, Oracle sends EXTERNALAGV instead of externalAGV and authentication fails.

SELECT * FROM "agv_inputqueue"@AGV;

If the query returns no rows selected, the link works. The tables are simply empty at this stage.

6.8 — Create Oracle synonyms

Still connected as db_read:

CREATE SYNONYM agv_age FOR "agv_age"@AGV;
CREATE SYNONYM agv_ags FOR "agv_ags"@AGV;
CREATE SYNONYM agv_eag FOR "agv_eag"@AGV;
CREATE SYNONYM agv_inputqueue FOR "agv_inputqueue"@AGV;
CREATE SYNONYM agv_outputqueue FOR "agv_outputqueue"@AGV;

Table names in double quotes are lowercase because PostgreSQL stores identifiers in lowercase by default.

Verify all synonyms: SELECT * FROM agv_inputqueue; (repeat for each). All queries must pass without error (no rows selected is expected).

Step 7 — Install the AGV module in Easy WMS

7.1 — Modify response.xml

Add the AGV entries in the deployment response.xml:

<ExtraApps>
    <Item Use="Yes" Name="AGV"
        Url="http://[host]/packages/Mecalux.ITSW.AGV.Application.zip"
        PackageUrl="http://[host]/packages/AGV.zip" />
</ExtraApps>

<Modules>
    <Module Name="AGV" LicenseLevel="ENABLED" />
</Modules>

7.2 — Run the deploy

Execute the deploy using option 16 — Install application.

7.3 — Restart the Gateway AGV

After the deploy completes, restart the Gateway AGV service in services.msc.

Troubleshooting

DSN name case: PostgreSQL35W

The most frequent cause of failure. The DSN name must be identical (case-sensitive) across all 6 locations:

File / Location Expected value
ODBC System DSN (data source name) PostgreSQL35W
tnsnames.ora (TNS entry name + SID) PostgreSQL35W
listener.ora (SID_NAME) PostgreSQL35W
initPostgreSQL35W.ora (filename) initPostgreSQL35W.ora
initPostgreSQL35W.ora (content) HS_FDS_CONNECT_INFO = PostgreSQL35W
CREATE DATABASE LINK ... USING '...' 'PostgreSQL35W'

Indentation in tnsnames.ora

The TNS entry identifier (e.g., PostgreSQL35W =) must start at column 1, with no leading space or tab. Accidental indentation causes ORA-12154: TNS:could not resolve the connect identifier specified.

Placeholder in listener.ora

The ORACLE_HOME in the PostgreSQL35W SID_DESC must be the real path. Leaving a placeholder like [VERSION] causes TNS-12518 / ORA-28545. The listener starts without error and the SID appears in lsnrctl status, which makes the problem difficult to spot. Verify with: dir C:\Mecalux\Motor\oracle\Product\

PostgreSQL 18+ port

PostgreSQL 18 defaults to port 5433 instead of 5432. Update two locations: the ODBC System DSN (Step 3) and the Gateway AGV connection string (Step 4).

Double AGVConfig section

The Gateway XML config must contain exactly one <AGVConfig> section. Two sections (even with different stationNumber values) cause: System.ArgumentNullException: Migration DataBase Provider No Initialized.

Double quotes in Oracle commands

Oracle converts identifiers to uppercase; PostgreSQL stores them in lowercase. When creating the database link and synonyms, PostgreSQL table names must be in double quotes ("agv_inputqueue"), and PostgreSQL credentials must also be in double quotes ("externalAGV", "mecalux").

The database link and synonyms must be created while connected as db_read, not SYS. A link created under SYS is not visible from db_read, and the AGV monitoring views in the WMS use the read model schema.

dg4odbc trace for diagnosis

If the DBLink fails (ORA-28545, ORA-12154, etc.), enable tracing in [ORACLE_HOME]\hs\admin\initPostgreSQL35W.ora:

HS_FDS_TRACE_LEVEL = 4

Restart the listener, retry the query, then look for the trace file in [ORACLE_HOME]\hs\admin\ or the Oracle diagnostic directory. Reset to 0 after diagnosis. If no trace file is created, dg4odbc is not launching at all - the problem is in listener.ora (incorrect ORACLE_HOME or listener not restarted).

Standalone ODBC connectivity test

To isolate an ODBC connection problem (bypassing Oracle/dg4odbc):

$conn = New-Object System.Data.Odbc.OdbcConnection
$conn.ConnectionString = "DSN=PostgreSQL35W;Uid=externalAGV;Pwd=mecalux;"
$conn.Open()
$conn.State    # Should display "Open"
$conn.Close()

If this test passes but the Oracle DBLink fails, the problem is in the dg4odbc configuration (Oracle files), not the ODBC connection itself.