Steps for IoT file download using Rest Client

Hello team,

I need some advice regarding IoT file download using Rest Client. Is it possible to download a file using OOB functionality of the Rest Client? They have exposed the file through GET - Serves files directly from a mounted directory over HTTP, so MES can retrieve a specific file by name without needing SFTP access.
In order to simulate this for automation testing, what would need to be done in order to host a file with a mock Rest Server?

I came across the documentation for the Rest server(Rest Server - Critical Manufacturing Developer Portal) and Mock MES instance(Connecting to a Live MES - Critical Manufacturing Developer Portal) and received confirmation from CMGPT that setting this up is possible using the steps outlined below. I would like to kindly seek your confirmation if these steps are correct.

Possible answer:

  • :white_check_mark: Yes, it is possible — the IoT Test Orchestrator’s Rest Server Simulator Plugin (RestServer.PluginMain) is the OOTB mechanism to host a mock HTTP server that serves files over GET for automation testing.
  • :white_check_mark: The plugin is powered by WireMock, supports registering GET endpoints via restSimulator.Register(), and returns file content through a SystemReply(200, fileContent).
  • :white_check_mark: The mock server address/port is injected into the MES dataflow JSON so the REST Client driver targets it instead of the real external system.

The Right Tool — Rest Server Simulator Plugin

A Simulator Plugin mirrors the implementation of its corresponding automation protocol. Since the MES uses a REST Client driver to retrieve files, a REST Client requires a REST Server simulator. The IoT Test Orchestrator Framework provides exactly this with the dedicated Rest Server simulator plugin

Steps:

  1. Add the Rest Server simulator plugin to the test scenario configuration
  2. Register a GET endpoint that returns the file content as SystemReply
  3. Read the file from disk in the test and return it in the handler
  4. Configure the Rest Client driver in MES to point to the mock server address

:clipboard: Step-by-Step Setup

Step 1 — Add the Rest Server Plugin to the Scenario Configuration

To add the Rest Server simulator plugin to a test scenario, include its configuration in ScenarioConfiguration:

var port = new Random().Next(5000, 30000); // randomize to avoid concurrency collisions

var configuration = new ScenarioConfiguration()
    .ManagerId("Manager01")
    // ... other settings ...
    .AddSimulatorPlugin<RestServer.PluginMain>(new RestServer.Plugin.SettingsBuilder()
        .Address("http://localhost", port)
        .ServerSettings(new WireMock.Settings.WireMockServerSettings()
        {
            StartAdminInterface = true
        })
        .Build())
    .Build();

The Rest Server configuration properties are:

Property Type Description Default
Address string Address —
Port int Port 8080
WireMockServerSettings object Server Settings — 3

Step 2 — Register a GET Endpoint That Serves the File

Inside your test, retrieve the Rest Server simulator and register a GET endpoint that reads and returns the file content:

var restSimulator = (RestServer.PluginMain) context.Simulators["RestServer"];

// Read the file content from disk
var fileBytes = File.ReadAllBytes("path/to/your/testfile.csv");
var fileContent = Convert.ToBase64String(fileBytes); // or return as string if text

restSimulator.Register("/files/myfile.csv", (ISystemRequest request) =>
{
    // Return the file with HTTP 200 and appropriate content
    return new SystemReply(200, System.Text.Encoding.UTF8.GetString(fileBytes));

}, Common.Objects.Rest.RestVerb.Get);

The OOTB usage example for the Rest Server plugin shows registering a GET endpoint with restSimulator.Register(), providing the route, a handler lambda that returns a SystemReply(statusCode, body), and the HTTP verb.


Step 3 — Point the MES REST Client Driver to the Mock Server

In the Mock MES configuration, update the restMasterDataPath JSON to use the dynamically assigned port so the Rest Client driver targets the mock server address:

// Update the dataflow JSON to use the selected port
File.WriteAllText(
    restMasterDataPath,
    File.ReadAllText(restMasterDataPath).Replace("5000", port.ToString())
);

This ensures the MES REST Client in the workflow sends its GET /files/myfile.csv request to the mock server instead of the real external system.


Step 4 — Verify the File Was Requested

var fileWasRequested = false;

restSimulator.Register("/files/myfile.csv", (ISystemRequest request) =>
{
    fileWasRequested = true;
    var fileBytes = File.ReadAllBytes("path/to/testfile.csv");
    return new SystemReply(200, System.Text.Encoding.UTF8.GetString(fileBytes));
}, Common.Objects.Rest.RestVerb.Get);

// ... trigger the MES workflow ...

scenario.Utilities.WaitFor(50, "File was never requested", () => fileWasRequested);

Thank You.

Hi,
For testing the test orchestrator docs are here Rest Client - Critical Manufacturing Developer Portal. I would point out that for large files you probably need an http stream which I think it’s not supported in the Rest Client or Rest Server.

Hi,

Yes, as João Roque said, the Rest Client driver cannot retrieve a raw binary response, such as application/pdf, image/png, or application/octet-stream. As workarround, you could use an endpoint that returns the file as text, or one that returns it Base64-encoded inside a JSON response.

Below, I describe how you could configure both these scenarios:

Scenario 1: Downloading a Text/XML File

The rest client driver never writes to disk. It returns the content into the workflow, and a File driver command writes it. A download is therefore two commands: one on the REST Client protocol to fetch the content, and one on the File protocol to write it.

For a text response, such as the one below, the content arrives as a String.

{
    "Name": "DownloadReport",
    "Description": "Retrieve the daily report as CSV",
    "DeviceCommandId": "/reports/:reportId",
    "ExtendedData": {
        "requestMethod": "GET",
        "timeout": 60000,
        "successfulStatusCodes": "200"
    },
    "Parameters": [
        {
            "Name": "reportId",
            "DataType": "String",
            "AutomationProtocolDataType": "String",
            "ExtendedData": {
                "operationParameters": "PathParameter"
            },
            "IsMandatory": true
        }
    ]
}

In the workflow, should connect the output of the Execute Equipment Command task that runs this command to the content parameter of a CreateFile command on the File driver:

{
    "Name": "WriteReport",
    "Description": "Write the retrieved report to disk",
    "DeviceCommandId": "WriteReport",
    "ExtendedData": {
        "commandType": "CreateFile"
    },
    "Parameters": [
        { "Name": "path", "DataType": "String", "AutomationProtocolDataType": "String", "IsMandatory": true },
        { "Name": "content", "DataType": "String", "AutomationProtocolDataType": "String", "IsMandatory": true }
    ]
}

Scenario 2: Binary File Through a Base64 Response

Many document APIs return a binary file as a Base64 string inside a JSON object, for example:

{
    "fileName": "certificate-4471.pdf",
    "content": "JVBERi0xLjQKJcfsj6IKNSAwIG9iago8PC9MZW5ndGgg..."
}

The driver parses that response as JSON and returns it as an Object. Extract fileName and content with a converter, then write the file with a CreateFile command whose encoding parameter is set to base64, which decodes the string back to the original bytes:

{
    "Name": "WriteCertificate",
    "Description": "Write a Base64 payload to disk as a binary file",
    "DeviceCommandId": "WriteCertificate",
    "ExtendedData": {
        "commandType": "CreateFile"
    },
    "Parameters": [
        { "Name": "path", "DataType": "String", "AutomationProtocolDataType": "String", "IsMandatory": true },
        { "Name": "content", "DataType": "String", "AutomationProtocolDataType": "String", "IsMandatory": true },
        { "Name": "encoding", "DataType": "String", "AutomationProtocolDataType": "String", "IsMandatory": false }
    ]
}

Set encoding to base64 when the command is executed. Leaving it at the default of utf-8 writes the Base64 text itself rather than the decoded file.

As a side note this is also common in OPC-UA. In that protocol we do support having retrieving files from OPC-UA and then writing them somewhere or sending them to the MES Read File - Critical Manufacturing Documentation Portal