Main Content

Create External File Adapter for Loading Variables into Simulink.SimulationInput Object

You can create and register a custom file adapter that the loadVariablesFromExternalSource function uses to load variables from a custom external source file into a Simulink.SimulationInput object. This simulation object allows you to temporarily make changes to a model and run simulations with those changes. To create an adapter for your custom file format:

  1. Write a class definition for your custom file adapter derived from the Simulink.data.adapters.BaseMatlabFileAdapter base class.

  2. Test that the adapter can load data from a supported external file source.

  3. Register the adapter and make it available on the MATLAB® path.

Write Class Definition for Custom File Adapter

In this example, write a custom file adapter for an XML file with a format similar to the following.

<customerData>​
  <x>10</x>
  <y>15</y>​
</customerData>

To write a custom file adapter, you must first create a new class that derives from the base file adapter class Simulink.data.adapters.BaseMatlabFileAdapter.

classdef xml_adapter < Simulink.data.adapters.BaseMatlabFileAdapter​

Required File Adapter Code Definitions

In your new file adapter class, you must provide code definitions for these methods:

The getAdapterName method provides the display name for the adapter. This display name is used by the Simulink.data.adapters.catalog function to list available registered adapters. The display name is also used in the user interface and in error messages.

function name = getAdapterName(adapterObj)
    name = 'XML Adapter';
end

The getSupportedExtensions method defines the file extensions that the file adapter supports. When you call the loadVariablesFromExternalSource function, Simulink® uses this method to determine if there is a registered adapter that supports the format of the external source file. Use the Simulink.data.adapters.catalog function to display registered adapters and their supported extensions.

function fileExtensions = getSupportedExtensions(adapterObj)
    fileExtensions = {'.XML'};
end

The getData method populates the data from an external source file into a workspace for that data source. The method receives a Simulink.data.DataSourceWorkspace object and an empty diagnostic structure.

The method reads data from the external source and populates it into the workspace object in the form of MATLAB variables and objects. The workspace acts as a cache for Simulink, and symbol resolution includes symbols in the workspace. Using the workspace object functions, you can interact with a data source workspace just as you do with a base workspace. You can get, set, clear, list, and query variables in the workspace and run MATLAB scripts.

The empty diagnostic structure allows you to specify error information that the getData method can return. The diagnostic structure has these fields.

FieldDescription
AdapterDiagnostic

Type of error, specified as an enumeration value from the enumeration class Simulink.data.adapters.AdapterError. These are the possible enumeration values.

  • NoDiagnostic (default)

  • GenericFailure

  • HardError

  • Inaccessible

  • AmbiguousSource

  • NoPermission

  • UnrecognizedFormat

  • Unsupported

DiagnosticMessageMessage to return as the error text, specified as a string. When AdapterDiagnostic is set to NoDiagnostic, the value is an empty string.

Here is an example of a getData implementation for your XML file. Because each call to the getData method on the same source file uses the same data source workspace object as the last call to the method, begin the getData code definition by clearing the variables from the workspace.

function diagnostic = getData(adapterObj, sourceWorkspace, previousChecksum, diagnostic)​
    % Each time getData is called on the same source, sourceWorkspace is the same as
    % the last time it was called. Clear it to make sure no old variables exist.
    clearAllVariables(sourceWorkspace);
    dom = xmlread(adapterObj.source);
    tree = dom.getFirstChild;
    if tree.hasChildNodes
        item = tree.getFirstChild;
        while ~isempty(item)
            name = item.getNodeName.toCharArray';
            if isvarname(name)
                value = item.getTextContent;
                setVariable(sourceWorkspace, name, str2num(value));
            end
            item = item.getNextSibling;
        end
    end
end

Optional File Adapter Code Definitions

In addition to the code definitions you must provide for your file adapter, you might also choose to override the code definitions for these methods:

  • open — Called when the file adapter is first loaded. By default, this method saves the source file name and section name as properties of the file adapter.

  • close — Called when the file adapter is finished.

  • isSourceValid — By default, this method validates that the source file exists and that the file adapter supports the file extension.

  • supportsReading — By default, this method validates that the source file has read attributes. You can override this method to allow multiple adapters to read the same file types but with different headers. For example:

    function retVal = supportsReading(adapterObj, source)​
        retVal = false;​
        % call base class method to ensure permissions are correct​
        if supportsReading@Simulink.data.adapters.BaseMatlabFileAdapter(adapterObj, source)​
            dom = xmlread(source);​
            tree = dom.getFirstChild;​
            if strcmpi(tree.getNodeName, "customerData")​
                retVal = true;​
            end​
        end​
    end​

  • getSectionNames — By default, this method returns the adapter display name returned by the getAdapterName method. You can override the method to define a logical division of the data contained in the external file. For example, consider a car manufacturer with a spreadsheet containing data for different tires. A file adapter used to load data from the spreadsheet can divide the data into sections based on the tire manufacturer. This section definition allows the car manufacturer to load the data into a set of Simulink.SimulationInput objects (one for each type of tire) that can be used by the parsim function to run parallel simulations.

  • getCurrentChecksum — By default, this method returns the timestamp for the last modified date of the file. The cache uses this method to determine if the adapter needs to get updates from the external file.

Test Custom File Adapter

Before registering your file adapter, you can test that it can load variables from a supported external source file by using a Simulink.data.adapters.AdapterDataTester object. Create the test object using an instance of your custom file adapter class, an external source file, and a section name.

adapterTester = Simulink.data.adapters.AdapterDataTester(adapterObj, 'test.xml','XML Adapter');

The readFromSource function of the Simulink.data.adapters.AdapterDataTester object calls the getData method for your adapter and returns the variables read from the external source file into the WorkspaceVariables property of the tester object.

readFromSource(adapterTester);
variables = adapterTester.WorkspaceVariables

The WorkspaceVariables property is a containers.Map object that uses the variables as the key set.

variables = 
  Map with properties:
    Count: 2
    KeyType: char
    ValueType: double
variables.keys
ans = 
  1x2 cell array
    {"x"}  {"y"}
variables[x]
ans = 
  10
variables[y]
ans = 
  15

To test the adapter again with different data in the file, first use the clear function to clear the workspace variables.

clear(adapterTester);

Then, update the XML file with this data.

<customerData>​
  <a>3</a>
  <b>4</b>​
</customerData>
readFromSource(adapterTester);
variables = adapterTester.WorkspaceVariables
variables = 
  Map with properties:
    Count: 2
    KeyType: char
    ValueType: double
variables.keys
ans = 
  1x2 cell array
    {"a"}  {"b"}
variables[a]
ans = 
  3
variables[b]
ans = 
  4

Register Custom File Adapter

Now that you have written and tested your file adapter, you must register the adapter before it can be used. Consider adding the registration to a startup script, since an adapter must be registered at the start of each MATLAB session. These functions allow you to manage your file adapter registrations.

Use Custom File Adapter to Load Variables for Simulation

Once you have registered the file adapter, it is available for use by the loadVariablesFromExternalSource function to load data from files supported by the adapter.

See Also

| | | | |