Local debuggin of Azure IoT Edge module with Visual Studio Code
Published: 2022-04-15 16:06:01

# Summary
[Azure IoT Edge module](https://docs.microsoft.com/en-us/azure/iot-edge/iot-edge-modules?view=iotedge-2020-11) is containerized application written with programming languages such as C# and Python, but it cannot run standalone without [Azure IoT Edge runtime](https://docs.microsoft.com/en-us/azure/iot-edge/iot-edge-runtime?view=iotedge-2020-11) due to its dependency. In this article, I am trying to explain how to run local debugging of IoT Edge module with Visual Studio Code.

# TOC
- [Concept](#concept)
- [Step by step](#step-by-step)
  - [1. Install IoT Edge Simulator](#install)
  - [2. Get Azure IoT Edge Device connection string](#connection-string)
  - [3. Set up IoT Edge Simulator](#setup)
  - [4. Start IoT Edge Simulator](#start)
  - [5. Get EdgeHubDev connection string](#edgehubdev)
  - [6. Set up debuggin environment of VS Code](#vscode)
  - [7. Start debuggin at VS Code](#debug)

# Concept <a name="concept"></a>

If you locally run your IoT Edge module without IoT Edge runtime, a method below in `Init()` causes an error because it has dependency of IoT Edge hub.

```
ModuleClient ioTHubModuleClient = await ModuleClient.CreateFromEnvironmentAsync(settings);
```

You would see an error like this

```
Exception has occurred: CLR/System.InvalidOperationException
An exception of type 'System.InvalidOperationException' occurred in System.Private.CoreLib.dll but was not handled in user code: 'Environment variable IOTEDGE_WORKLOADURI is required.'
```

- IoT Edge module cannot run without IoT Edge runtime at the local machine
- Instead of IoT Edge runtime, the local machine can run the module with IoT Edge Simulator
- Local run requires a connection string of `EdgeHubDev` container as a local environment variable

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d1tdduqn3rzxkchti5tx.png)
 
# Step by step <a name="step-by-step"></a>
## 1. Install IoT Edge Simulator <a name="install"></a>

Install IoT Edge Simulator in the local machine with Python (2.7/3.6/3.7/3.8) 
```
pip install --upgrade iotedgehubdev
```
## 2. Get Azure IoT Edge Device connection string <a name="connection-string"></a>

- Deploy Azure IoT Hub
- Create IoT Edge device
- Get the device connection string

## 3. Set up IoT Edge Simulator <a name="setup"></a>

Set up IoT Edge Simulator with the IoT Edge Device you registered in the Azure IoT Hub
```
iotedgehubdev setup -c "{Device connection string}"
```

## 4. Start IoT Edge Simulator <a name="start"></a>
Start the IoT Edge Simulator containers
```
iotedgehubdev start
```

Check out if the containers are running with `docker ps -a`
```
CONTAINER ID   IMAGE                                                  COMMAND                   CREATED          STATUS          PORTS                                                                            NAMES
a33ff8d28606   mcr.microsoft.com/azureiotedge-testing-utility:1.0.0   "node server.js"          47 minutes ago   Up 47 minutes   0.0.0.0:53000->3000/tcp                                                          input
5609dbc7596c   mcr.microsoft.com/azureiotedge-hub:1.2                 "/bin/sh -c 'echo \"$…"   47 minutes ago   Up 47 minutes   0.0.0.0:443->443/tcp, 0.0.0.0:5671->5671/tcp, 0.0.0.0:8883->8883/tcp, 1883/tcp   edgeHubDev
```

## 5. Get EdgeHubDev connection string <a name="edgehubdev"></a>

Get the connection string of EdgeHubDev module
```
iotedgehubdev modulecred
```

Below is an output example. There are the connection string and certificate location. The connection string is enough to run the module locally.

```
EdgeHubConnectionString=HostName=iot-sample.azure-devices.net;GatewayHostName={Local Machine Name};DeviceId={IoT Edge Device Name};ModuleId=target;SharedAccessKey=xxxxxxxxxxxxx
EdgeModuleCACertificateFile=/home/username/.iotedgehubdev/data/certs/edge-device-ca/cert/edge-device-ca.cert.pem
```

## 6. Set up debuggin environment of VS Code <a name="vscode"></a>

Set up Visual Studio Code with WSL2.

Go to `.vscode/task.json` and set up the build configuration

```
tasks": [
    {
      "label": "build",
      "command": "dotnet",
      "type": "process",
      "args": [
        "build",
        "${workspaceFolder}/src/SampleModule/SampleModule.csproj",  
        "/property:GenerateFullPaths=true",
        "/consoleloggerparameters:NoSummary"
      ],
```

Go to `.vscode/launch.json` and set up the debug run configuration. Set the environment variable `EdgeHubConnectionString` you extracted in the previous step.

```
"configurations": [
    {
      "name": ".NET sample module",
      "type": "coreclr",
      "request": "launch",
      "preLaunchTask": "build",
      "program": "${workspaceFolder}/src/SampleModule/bin/Debug/net6.0/SampleModule.dll",
      "args": [],
      "cwd": "${workspaceFolder}/src/SampleModule",
      "console": "internalConsole",
      "stopAtEntry": false,
      "env": {
        "EdgeHubConnectionString": "HostName=iot-sample.azure-devices.net;GatewayHostName={Local Machine Name};DeviceId={IoT Edge Device Name};ModuleId=target;SharedAccessKey=xxxxxxxxxxxxx"
      }
    },
```

## 7. Start debuggin at VS Code <a name="debug"></a>

Start a debug run at Visual Studio Code