The **Azure IoT TypeEdge** introduces a strongly typed flavor of the inherently loosely coupled vanilla [Azure IoT Edge](https:/azure.microsoft.com/en-us/services/iot-edge/).
2.**Install the latest [.NET Core](https://github.com/dotnet/core/blob/master/release-notes/download-archive.md)**
> ***Important note***: **TypeEdge** requires **.NET Core 2.1.0-Preview2** and above, you can check your version by typing:
```cmd
dotnet --version
```
> *As of 05/25/2018, the latest .NET Core release is [this](https://github.com/dotnet/core/blob/master/release-notes/download-archives/2.1.0-rc1-download.md)*
1.**Install your favorite IDE ([VS Code](https://code.visualstudio.com/download) or [VS 2017](https://www.visualstudio.com/downloads/))**
1.**Temporary step - private NuGet packages**:
Temporarily, and until GA, the required NuGet packages will be distributed through [this](https://msblox-03.pkgs.visualstudio.com/_packaging/private-nuget-feed/nuget/v3/index.json) private NuGet feed. After GA, these packages will be available in the www.nuget.org.
> ***Important note:*** Only MS FTE have access to this NuGet feed. To add the feed to your machine wide configuration just once. This is required because of the way dotnet templates at the moment work.
To add the feed to your machine you will need your git credentials or a personal access token. TO get your git credentials, navigate to the [VSTS repo](https://msblox-03.visualstudio.com/csetypescript) and under **"clone to your computer"** section, click **"Generate Git Credentials"**
Here is the quickest way to get started with TypeEdge. This quick start will create an IoT Edge solution with two modules and run it in the IoT Edge emulator:
>**Note:** If you already installed the template and you want to **update to a newer template version**, you need to clear the dotnet http and template cache
2. Copy the **iothubowner connection string** from your development Azure **IoT Hub**.
> The **iothubowner** is required because TypeEdge needs to provision a new device with the generated deployment configuration.
1. Create a new IoT TypeEdge application:
> You can choose the TypeEdge application and modules names of this template. In the example bellow, the application is called **Thermostat**, and the two modules are called **SensorModule** and **PreprocessorModule**. These names will be used as class names, so **Pascal casing** is suggested.
**Congratulations!** You just created your first TypeEdge application. Continue reading bellow to learn how to deploy this application to an IoT Device
This module has a strongly typed output called ***Output*** and the messages type is ***SensorModuleOutput***. Similarly, it has a module twin called ***Twin*** with type ***SensorModuleTwin***
> Note: **TypeEdge** allows you to define multiple twin properties to enable partial twin updates
Finally, this module has a method that can be invoked directly with the bellow method signature:
```cs
bool ResetModule(int sensorThreshold);
```
### Module implementation
After describing the module behavior and structure with an interface, the next step is to implement this interface. This is effectively the code that will run in the **TypeEdge** module. Below is an implementation example of the above interface:
A **TypeEdge** module can override any of the virtual methods of the base class ``EdgeModule``. As demonstrated in the above example, the ``RunAsync`` method is used for implementing long running loops, typically useful for modules that read sensor values. Another virtual method is ``Configure``, which can be used to read custom module configuration during startup. Finally, the ``BuildSubscriptions`` is used to define handlers to incoming messages.
The complete ``EdgeModule`` definition is:
```cs
public abstract class EdgeModule
{
public EdgeModule();
public virtual void BuildSubscriptions();
public virtual CreationResult Configure(IConfigurationRoot configuration);
public virtual Task<ExecutionResult> RunAsync();
}
```
### Module Subscriptions
**TypeEdge** uses the pub/sub pattern for all module I/O, except for the direct methods. This means that a module can subscribe to other module outputs, and publish messages to their inputs. To do this, a reference to the module interface definition is required. **TypeEdge** uses dependency injection to determine the referenced modules.
Bellow, is the constructor of the second module included in the application template called ``PreprocessorModule``, that references the ``SensorModule`` via its interface.
```cs
public PreprocessorModule(ISensorModule proxy)
{
this.proxy = proxy;
}
```
Using this proxy, the ``PreprocessorModule`` module can interact with the ``SensorModule``:
In this example, the ``PreprocessorModule's`` input called ``Input``, subscribes to ``SensorModule's`` output, called ``Output``, and defines a subscription handler, a delegate that will be called every time the ``SensorModule`` sends a messages through its ``Output ``. In this example, the ``PreprocessorModule`` will enrich the incoming message, and publish it to its output called ``Output ``. These subscriptions need to be declared in the ``BuildSubscriptions`` override.
The complete code of the template's ``PreprocessorModule`` is:
The emulator references the Runtime bits achieve the emulation. Under the hood, the emulator starts a console application that hosts the Edge Hub and all referenced modules. It will also provision a new Edge device to your designated IoT Hub (by the iothubowner connection string). This device will contain a fully functional deployment configuration, ready to be used to an actual device deployment.
To reference modules in an emulator application, both the interface and the implementation class of the module is required:
**TypeEdge** adds functionality also for service application development (cloud side application). This template will create a Proxy project, useful for cloud side interaction with the TypeEdge application. It also leverages the interfaces as the way to create a strongly typed proxy client. The code to call a direct method of a TypeEdge module from the could side is literally one line:
Apparently, to reference module definition interfaces and to avoid coupling the module implementation code together, these interfaces need to be defined in a separate project that will be commonly shared across the solution, containing only the definition interfaces and the referenced types.