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.
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.
// 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:
Use IControllerProvider
to get an instance of the Aerotech.Automation1.DotNet.Controller
object. This object is the entry point for the .NET API to access all of the features of the connected controller. If nested views require access to the controller, your module can pass a reference to the IControllerProvider
.
IMPORTANT: In a custom module, you must use an IControllerProvider
. Do not call Aerotech.Automation1.DotNet.Controller.Connect()
to access the controller object. This makes sure that you are accessing the controller that the MachineApp is connected to.
Use INotificationProvider
to make toast notifications that appear in the top-right corner of the MachineApps application. This lets your module get the attention of the user with different severity options. You can also see these notifications in the Notifications tab of the application sidebar.
Use the IDialogProvider
to show dialogs to the user. This includes simple acknowledgment dialogs that you can customize with specific messages, captions, and button sets. It also includes dialogs that interact with files on the client PC or the controller file system.
Frequently Asked Questions
No. You can have as many modules as you want in a single dynamic link library. Modules must have unique names defined in their CustomModuleMetadata
.
Yes. You can have as many dynamic link libraries uploaded to the controller as you want. Each one will be scanned for custom modules. Modules must still have unique names across all of the dynamic link libraries.
Yes. You can include other dynamic link libraries that do not include any custom modules but are dependencies for your custom modules. These libraries must be uploaded from your Custom Modules working directory to the controller in Automation1 Studio.
After you make changes to your custom modules in Visual Studio, you must rebuild the project and make sure that your updated files are in your Custom Modules working directory. Then you can upload your working directory in Automation1 Studio. See the To Upload Your Custom Modules Configuration section of the MachineApps Workspace page. You must upload your working directory again and restart MachineApps in order for your changes to have an effect.
Yes. You can use the Download MCD tool in the Administration module of the Configure workspace in Automation1 Studio to download your MachineApps configuration, which will contain all of your MachineApps and your custom modules configuration. Then you can upload this MCD file by using the Upload MCD tool from the same module on the target controller.
IMPORTANT: When you upload MachineApps, this process will overwrite any existing custom modules configuration on the target controller.