Custom Modules

A MachineApp is a customized user interface that you can use to operate a machine that is controlled by an Automation1 controller. Custom Modules for MachineApps is a feature that lets you develop new modules that can be integrated and deployed with standard modules in a MachineApp.

Custom Modules interact with the Automation1 controller and other parts of the MachineApps Application through the use of Providers. One Provider gives your Custom Module access to an instance of the .NET Controller object, which represents the connected controller in MachineApps. This lets you use the full Automation1 .NET API in your Custom Module. Other providers expose more features that your module can access, such as showing dialogs or notifications.

Custom Modules can also contain other functionality. A Custom Module can access the local hardware and file system of the computer where the Automation1 MachineApps application is running. Your Custom Module can reference other .NET assemblies, native DLLs, or configuration files. You can manage these files and your compiled Custom Modules through the MachineApps workspace in Automation1 Studio. Custom Modules can also rely on drivers or other installed applications or components when these dependencies can be found and/or loaded dynamically by your code that is running under .NET.

Additional Technical Details

Custom Modules are written in C#, use Windows Presentation Foundation (WPF) UI technology, and target the .NET 6.0 Long Term Support (LTS) runtime. Custom Modules reference several types that are part of the Automation1 MDK and are compiled for use with a specific version of Automation1.

Custom Modules inherently support the Model-View-ViewModel (MVVM) design pattern, which lets you specify one type for your DataContext (typically your ViewModel) and a different type for your UserControl. But you also have the flexibility to define all of your logic in the code-behind of your UserControl.

Automation1 MachineApps uses Dependency Injection and Reflection to create instances of your Custom Module types at runtime and give your Custom Module types instances of the Providers that they require. It is not necessary for you to call the constructor on your Custom Module or find the Providers that you need. The MachineApps Application does this for you when your Custom Modules are loaded with the standard modules that you add to a MachineApp.

Getting Started with the Example Project

The CustomModulesExample is a Visual Studio Solution that shows you how to create a custom module. This project has two modules in it that demonstrate an MVVM and a non-MVVM method for creating a custom module.

Project Location

You can find the custom modules example project in the installation directory of the Automation1 MDK. The path to the example is: …\Aerotech\Automation1-MDK\MachineApps\Examples\CustomModulesExample.

Project Structure

The CustomModulesExample solution has two folders. One folder is for the Analog Inputs Module and the other is for the Analog Outputs Module.

Analog Inputs Module

This custom module uses the MVVM pattern by registering a view (AnalogInputsView) and a view model (AnalogInputsViewModel). When an instance of the module is created, the AnalogInputsViewModel is created and set as the DataContext of the AnalogInputsView. The view model implements INotifyPropertyChanged to let data binding occur. The view model also takes an IControllerProvider and an INotificationProvider as dependencies that are injected by the application when the module is created.

Analog Outputs Module

This custom module does not use the MVVM pattern. It has an AnalogOutputsView that defines the user interface in the AnalogOutputsView.xaml and has additional logic in the code-behind (AnalogOutputsView.xaml.cs). The AnalogOutputsRegistration sets the DataContext property to null to indicate that there is no view model in this condition. The AnalogOutputsView constructor can take providers as arguments that are injected by the application when the module is created.

Project Output

When you build the example project in Visual Studio, this process makes a dynamic link library (DLL) with the name CustomModulesExample.dll. This file contains all the things that are necessary for you to use the example custom modules in a MachineApp. But before you do this, you must use Automation1 Studio to upload the file to a controller. For information about how to do this, see the To Upload Your Custom Modules Configuration section of the MachineApps Workspace page.

API Overview

When you create a custom module, there are two specific types you will need. They are CustomModuleRegistration and CustomModuleMetadata. The CustomModuleRegistration type is abstract. It will be inherited from in order to register your module. It is not necessary for you to create an instance of this type. Studio and MachineApps will create instances through reflection when necessary.

CustomModuleRegistration

The CustomModuleRegistration type is an abstract class that is necessary to register a custom module with Studio so you can use it in MachineApps. When you use the Manage Custom Modules dialog in the MachineApps workspace to edit the custom modules configuration, Studio uses reflection to identify classes that inherit from CustomModuleRegistration and read the Metadata property for that module. This metadata is used by the MachineApp builder when it designs a MachineApp and provides information about the module name, type, and how you can use it.

The CustomModuleRegistration has two other properties. They are the UserControlType and the DataContextType. These properties are not instances of the module user control or data context. But these properties are their Type. When it is necessary to use an instance of a custom module in a MachineApp, the application creates an instance of the applicable type.

Tip: If you know a lot about the MVVM pattern, you can define the UserControlType and the DataContextType properties.

When the module is created, an instance of the view and the view model are also created. The view model is set as the DataContext for the view. If you do not use the MVVM pattern, then it is only necessary to define a UserControlType for your module. Refer to the example that follows.

Copy
public class MyModuleRegistration : CustomModuleRegistration
{
    public override CustomModuleMetadata Metadata => new CustomModuleMetadata("My Custom Module");

    public override Type UserControlType => typeof(MyView);

    public override Type DataContextType => typeof(MyViewModel);
}

CustomModuleMetadata

The CustomModuleMetadata type specifies information about your custom module.

The Name property specifies the unique name that will identify your module. The application shows it while you are designing a MachineApp.

The MachineAppModuleType property lets you put the module into Primary or Secondary regions when you design a MachineApp. The default value is MachineAppModuleType.Primary.

The ModuleOrientation property lets you limit secondary modules to specific regions. This propety applies only if the MachineAppModuleType is MachineAppModuleType.Secondary. The default value is ModuleOrientation.Any.

The AllowMultipleInstances property lets you specify whether or not multiple instances of your custom module can exist in the same MachineApp. The default value is false.

Providers

Providers are types that are available for you to use in your custom modules. They can help you interact with the controller or the application. They also provide more features that your module can access. To use a provider, you must request it through dependency injection. To do this, include an argument with the type of the desired provided in your custom module user control or data context constructor. Make sure the type is one that is registered by the CustomModuleRegistration. When an instances of the module is created, MachineApps will provide an instance of the provider to the constructor. Refer to the example that follows.

Copy
// A Custom Module view model that takes a controller provider.
// Do not call this constructor. It will be called by
// MachineApps when your module is created.
public MyViewModel(IControllerProvider controllerProvider)
{
    this.controllerProvider = controllerProvider;
}

For more examples, see the CustomModulesExample project. Refer to the Getting Started with the Example Project section of this page for more information.

The providers that follow are available:

Frequently Asked Questions