Develop Plugins | Support Any Device & System | Share Your Robots
The MARS platform is independent of device brand, model or type. The platform is designed to support any device of any brand or type through plugins. Using the same plugin mechanism, the platform can also be used to send high-level commands to existing programs that control completed physical systems.
MARS Overview
Developer Downloads
Support/Questions or email: support at makeaffinity dot com.
Contents
- Support or email: support at makeaffinity dot com
Walkthroughs & Source Code
- Lego Mindstorms NXT Plugin (Bluetooth)

Developer Downloads
Developers, vendors, hobbyists, tinkerers, engineers, makers: Why plugins?
A plugin is a small piece of code that extends the function and ability of a piece of software or hardware. Anyone can write a plugin to extend their device or system. Everyone is encouraged.
The world is full of physical devices, controllers and micro-controllers. There are many platforms and languages, and an infinite number of possible project domains. No single person or organisation is able to realise the potential of all the devices. MakeAffinity's solution is to use plugin architecture so you can extend the capability of the device that you have bought, will buy or manufacture. We believe MakeAffinity opens up an exciting world of possibilities and hope that you think so too.
Plugins can be written in any of the dozens of .Net languages here and here.
What Can You Write Plugins For?
The plugin architecture is designed to allow the developer as much flexibility as possible. This means that plugins can be written for just about any purpose. The following are a few scenarios. Note that the scenarios may use code fragments to make the descriptions feel more concrete. The code fragments should become clearer as you move on to other sections of the plugin guide.
Scenario: Plugins can be written to control single purpose devices where there is a straightforward mapping between a plugin type's methods and a physical device's API (Application Programming Interface) methods. Here, the plugin can be written such that invocation of its methods will simply invoke the physical device's API methods straight through.
Example: The Phidget InterfaceKit 0/0/4 is a device that controls 4 relay switches and the states of each switch can be set with the following Phidgets API statement:
device.outputs[switchID] = state;
(The above statement simply sets a particular switch to a particular state.)
Here, the MakeAffinity.Plugin.Devices.Relay plugin type can be used to map directly to such a device, and the plugin type's SetState(int switchID, bool state) method can simply invoke the above statement directly.
See MakeAffinity.Plugin.Devices.Relay in Plugin API Help & Reference for detailed info and code examples.
Scenario: Plugins can be written to make a single device appear as multiple devices at the same time. For such devices, it is up to the plugin writer to decide which outputs and inputs will be used for what sub-devices and purposes. Certainly, different plugins can be written for the same physical device and each plugin can make the device appear to the MakeAffinity platform as different kinds or groups of devices.
Example: The Arduino Diecimila has 14 digital input/output pins, 6 of which can be used as PWM outputs. A digital output can make a motor or bulb go on or off. PWM outputs can simulate analog signals which can be used to make motors run at different speeds or bulbs light at different brightness, and e.t.c.
A plugin can be written to make the Diecimila appear to MakeAffinity as a single relay-type device (MakeAffinity.Plugin.Devices.Relay) that has 14 digital outputs for which one can set the states of (i.e. on or off). Another plugin can make the Diecimila appear as two relay-type devices, each with 7 digital outputs each.
A yet more sophisticated plugin can make the Diecimila appear as two different types of devices at the same time: A relay-type device with 8 digital outputs, as well as a motor-type device (MakeAffinity.Plugin.Devices.Motor) that uses its 6 PWM outputs to control a motor. To take things further, one can create two instead of just one motor-type devices out of the 6 PWM outputs.
Example 2: The Serializer WL .NET robot controller has, amongst other connectors, 6 servo, 2 motor and multiple digital I/O ports.
A plugin can be written to present the Serializer WL as several servo (MakeAffinity.Plugin.Devices.Servo), motor and relay devices at the same time!
The possibilities can be quite endless. A single physical device can be packaged with a set of different plugins, thus greatly expanding the capability and usefulness of the device out-of-the-box.
See MakeAffinity.Plugin.Manager in Plugin API Help & Reference for detailed info and code examples. (IKVM)
Scenario: Plugins can be written for devices of any type. The MakeAffinity platform currently supports the implementation of 3 specific (relay, servo and motor) and 2 all-purpose plugin types (TextBoxValues and TextBoxDropDownCheckboxValues). The all-purpose types can be used to support any type of device.
The all-purpose types are used to present different kinds of name-value input fields to the construct maker at the website: TextBoxValues presents each input field as a label (the field name) and a textbox (where the user can input a value), and TextBoxDropDownCheckBoxValues gives the plugin developer the choice of presenting each input field as a textbox, dropdownlist, or checkbox.
Both the TextBoxValues and TextBoxDropDownCheckBoxValues classes are mechanisms that simply pass the input values straight through to the plugin. What a plugin does with the received values is entirely up to the plugin developer.
See MakeAffinity.Plugin.Devices.TextBoxDropDownCheckBoxValues & MakeAffinity.Plugin.Devices.TextBoxValues in Plugin API Help & Reference for detailed info and code examples.
Scenario: Plugins can be written to control completed or whole physical systems by sending high-level commands to existing computer programs that control those systems. This is achieved by writing the plugin as a wrapper for your program - here, your plugin's methods will invoke functions in your other program.
Example: You have a robot (could be a car, could be an LED display, could be industrial, could be anything) and already has a program to control it using high level commands like 'walk forward 1 step' or 'walk backwards 1 step'. You no longer need to control your robot in terms of low level motor or servo commands that move the robot's individual gears and cogs, but wish to be able to tell your robot to move in steps.
To achieve this, you can develop a TextBoxValues plugin as a wrapper for your control program. The plugin can be made to display a "Walk" input field in the construct's Make Editor to ask the maker to enter a number. A positive number to walk forward or negative number to walk backwards or 0 to stop walking. These values can be stored as Actions and linked to buttons. The end result is that when the user of the construct clicks on the, for example, move forward button, the value of 1 is sent to your plugin where you can have code to make the robot move 1 step forward. You now have a construct that lets you control your robot across the web with minimal rework.
See MakeAffinity.Plugin.Devices.TextBoxDropDownCheckBoxValues & MakeAffinity.Plugin.Devices.TextBoxValues in Plugin API Help & Reference for detailed info and code examples.
Scenario: Plugins can be written to do anything that software applications can do - use TCP/IP or web services, send ethernet packets to operate ethernet control devices, start and stop other software applications (e.g. web browsers), or send, receive and process wireless signals (Bluetooth, WiFi, RFID, GPS) to other systems and e.t.c.
Pre-Requisites
The explanations on how to write plugins assume that you are familiar with what MakeAffinity is about and what it does. Specifically, you should have at least viewed a few constructs, as well as made one with either supported or dummy (see developer downloads) device plugins. Go here for help.
How It Works - An Overview
The MakeAffinity platform consists of the MakeAffinity website (www.makeaffinity.com) and the MakeAffinity client. The client is downloaded and installed and run on the same computer that your physical devices are connected to. The website communicates with your devices via the client and the client talks to your devices via plugins. Properties of the devices that are found by your client will show up automatically at the website (in your Make Editor).
The following is a figure of how the different parts of the platform communicate with each other:
Website -> Internet -> Client -> Plugins -> Devices
The client looks for plugins in the Program Files\MakeAffinity\makeaffinity\DevicePlugins folder. The client will treat any file in that folder that has a .dll extension as a MakeAffinity plugin file. Therefore, when you have a new plugin file, just copy it into that folder. The same goes when you are developing a plugin - just set the output path of your development project to that folder so the client can always use your latest compiled version.
The following figure shows a typical scenario with several plugins:
Client -> Brand A motor plugin -> Brand A motor device
-> Brand A servo plugin -> Brand A servo device
-> Brand B motor plugin -> Brand B motor device
-> Brand C relay plugin -> Brand C relay device
-> Physical system X plugin -> Physical system X (e.g. your robot)
-> Physical system Y plugin -> Physical system Y (e.g. your project)
-> any number of plugins -> any number of devices and systems
Plugin Development - The Wheres and the Whats
- Current plugins need to be .NET assemblies and need to be written in a .NET language (C#, VB.NET, Visual C++ with managed extensions, and possibly others listed at www.dotnetpowered.com/languages.aspx).
- .NET languages can be developed using the very nice and free Visual Studio Express series of integrated development environments.
- A possibly easy way of supporting existing compiled programs of any language is through .NET's interop facility, where a .NET wrapper for your program may be generated just by adding a reference to your program from within Visual Studio.
- Plugin files implement the abstract classes that are defined in MAFFDevice.dll.
- MAFFDevice.dll is installed as part of the MakeAffinity client (in Program Files\MakeAffinity\makeaffinity\bin). Do remember to add a reference to it so that your development project can find it.
- MakeAffinityDevicePluginAPI.chm contains detailed help and code examples on the MakeAffinity Plugin API (Application Programming Interface). The API describes what is inside MAFFDevice.dll and how to use it.
- The client looks for plugins in the Program Files\MakeAffinity\makeaffinity\DevicePlugins folder
- The status box on the MakeAffinity Client will display any status and error messages from your plugin or the client to help report any errors during development.
- More detailed messages and detailed exception reports are written to the log file at C:\Program Files\MakeAffinity\makeaffinity\Logs\log.txt.
- Step-by-step walkthroughs of how to develop plugins can be found here.
Plugin Development - An Overview
Each plugin file must contain one class that is derived from Manager (i.e. inherits from), and one or more classes that are derived from (i.e. inherits from) a supported plugin device type.
The Manager class is of type:
MakeAffinity.Plugin.Manager.Manager
The platform currently supports 5 plugin device types:
- MakeAffinity.Plugin.Devices.Relay
- MakeAffinity.Plugin.Devices.Servo
- MakeAffinity.Plugin.Devices.Motor
- MakeAffinity.Plugin.Devices.TextBoxValues
- MakeAffinity.Plugin.Devices.TextBoxDropDownCheckBoxValues
THE MANAGER CLASS
Your manager class must inherit from the MakeAffinity.Plugin.Manager.Manager type.
Your manager class is responsible for knowing how to create instances of the device classes that are contained in the same plugin file, and storing those instances in the Manager.MAFFDevices collection.
Manager.Initialise is a plugin file's first point of entry after the constructor. The Manager class has just 2 methods that you must implement: Initialise and Shutdown.
Typically, Manager.Initialise is responsible for searching for and identifying the physical devices that it knows about that are connected to your computer.
For example, let's say that you are writing a plugin for a Phidgets Servo Controller. The first task of your Manager.Initialise method will be to talk to the Phidget's driver to determine if there is a Phidgets Servo Controller connected to your computer. If there is, then Manager.Initialise will create an instance of YourPhidgetServoClass (which must also reside in the same plugin file) as a wrapper for the Phidgets device.
Where there are more than one device of the same type, the Manager should create multiple instances of that device but each with a different brand name, model name, and serial number COMBINATION so each instance is mapped to a physical device and can be uniquely identified by the MakeAffinity platform.
For example: you have 2 relay boards of the same brand and model connected to your computer, and each board has a unique serial number as defined by the boards' manufacturer. And in your plugin, you have defined 1 class called MyManagerClass and 1 class called MyRelayClass. In this case, the Initialise method of your manager class should create 2 instances of MyRelayClass each with different BrandName, ModelName, SerialNumber COMBINATIONS. I.e. the first device can be brand A, model B, serial number X; and the second device will be brand A, model B, serial number Y.
It is recommended that the brand, model and serial number definitions be based on manufacturer's details to prevent name clashes during device identification, especially when more plugins are added in the future. Ideally, a plugin developer should try to make brand, model and serial number combinations as globally unique as possible across all devices that exist now and can exist in the future. Adopting a device's manufacturer's brand, model and serial number should guarantee this.
Details of each method's purpose and code examples are contained in the Plugin API Help & Reference. The code examples are simple to understand. See also the walkthroughs on how to write a plugin.
THE DEVICE CLASSES
Each plugin device class must inherit from a MakeAffinity plugin device type. The device classes contain 2 sets of methods that you must implement.
The first are the 6 methods that are common across all devices: BrandName, ModelName, SerialNumber, Initialise, Shutdown, MakeSafeAll.
The second are methods that are specific to a device type's purpose and can be different for each type. For example, a relay device type has OutputCount, GetState, SetState; and a servo device has ServoCount, GetPosition, SetPosition.
Your device class is responsible for knowing how to talk to and control your device (usually through the device driver). The client will invoke the methods that your device class must implement. The names of the methods indicate the purpose of each method.
Similar to the manager class, device class also has an Initialise method. The method is responsible for bringing your device to a ready state. The Shutdown method is responsible for putting your device into a safe/off state, powering down (if possible), and freeing up resources. The MakeSafeAll method is responsible for bringing your device to a safe/off/stop state.
Details of each method's purpose and code examples are contained in the Plugin API Help & Reference. See also the walkthroughs on how to write a plugin.
Golden Rules of Plugin Development
- All methods can and will be invoked repeatedly and in any sequence. All methods must be programmed to check that any of the method's required resources are available before using them. For example, depending on the device, it may be necessary to check that a device is not already previously initialised before trying to initialise it. Another example, a device should be checked that it is already in an initialised state before an attempt is made to shut it down or make it safe or get its serial number or get it to do anything beyond initialisation.
- It is recommended that the brand, model and serial number definitions be based on manufacturer's details to prevent name clashes during device identification, especially when more plugins are added in the future. Ideally, a plugin developer should try to make brand, model and serial number combinations as globally unique as possible across all devices that exist now and can exist in the future. Adopting a device's manufacturer's brand, model and serial number should guarantee this.
- It is recommended that messages be kept to a minimum when the plugin is released for public use so as not to flood the Client's message display mechanism or the log file unnecessarily. Fewer messages may also make the client run quicker.