© Sibeesh Venu 2020
S. VenuAsp.Net Core and Azure with Raspberry Pi 4https://doi.org/10.1007/978-1-4842-6443-0_4

4. Creating and Deploying a .NET Core Application to Raspberry Pi

Sibeesh Venu1  
(1)
Birkenfeld, Germany
 

In the last chapter, we set up our machine. In this chapter, we are going to create a .NET Core application and deploy it to Raspberry Pi. This chapter assumes that you followed all the steps mentioned in Chapter 3. If you are not sure, please review that chapter.

Creating a .NET Core Application

By just running two commands, you can easily create a sample dummy application in VSCode. Later, we will be editing that solution. Sound good? If it does, open a new terminal and run the following commands.
mkdir raspberrypi.net.core && cd raspberrypi.net.core

This command will generate a new folder called raspberrypi.net.core and change the current working directory to that new folder. This cd command is also known as chdir (change directory).

Now run the following command to generate a new solution.
dotnet new console --langVersion=latest && dotnet add package iot.device.bindings
If everything goes well, it will do the following:
  • Create an empty console application, since we provided the console template in the command.

  • Perform some post-creation actions, such as dotnet restore.

  • Add the package reference that we provided in the command. In this case, it is iot.device.bindings. This iot.device.bindings package gives us a set of device bindings that use system.device.gpio to communicate with a microcontroller.

  • Restore the given package.

Once the restore is finished, all the required files and references will be available in our solution. The sample output is shown in Figure 4-1.
../images/488238_1_En_4_Chapter/488238_1_En_4_Fig1_HTML.jpg
Figure 4-1

Project creation output

Let’s open this folder and see which files were generated; see Figure 4-2.
../images/488238_1_En_4_Chapter/488238_1_En_4_Fig2_HTML.jpg
Figure 4-2

Created project folder structure

You can see that there is one folder called obj. This is where the temporary object files and other files are stored to create the final library. The final library is stored in the folder called bin, which we will explain once we compile our application. Now just right-click the root folder and open it in Visual Studio Code. If you don’t see the Open with Code option in the right-click menu, the easiest way to fix that issue is to reinstall VSCode and make sure to select the check boxes shown in Figure 4-3.
../images/488238_1_En_4_Chapter/488238_1_En_4_Fig3_HTML.jpg
Figure 4-3

Open with Code options should be selected

Note that you can also run code . from the command-line tool itself. Visual Studio Code will then open the project in the current folder.

If your VSCode displays a popup saying that a C# extension is recommended when you open the Program.cs file, go ahead and install it. See Figure 4-4.
../images/488238_1_En_4_Chapter/488238_1_En_4_Fig4_HTML.jpg
Figure 4-4

C# extension for VSCode

If you have ever wondered what is happening when you install an extension, you can see that process in the output window, shown in Figure 4-5.
../images/488238_1_En_4_Chapter/488238_1_En_4_Fig5_HTML.jpg
Figure 4-5

C# extension installation output

Now it’s time to run the application the first time. The easiest way is to press the F5 button; however, you can always go to the Run menu and click the Start Debugging submenu. If it asks you to select the environment, choose .NET Core.

A file called launch.json will be generated in the .vscode folder. This is where we set the debugging options for our application. You can also see that there is another file generated in the same folder, called task.json. This file specifies how to compile the project. We will be talking about these files in a coming section.

If everything goes well, you should see a "Hello World!" message in your debug console. If you are not sure where this message comes from, just look at the Program.cs file. This is how your Program.cs file looks:
using System;
namespace raspberrypi.net.core
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

You will be rewriting this code later. But before you do that, you need to make some changes to the Visual Studio Code.

Installing Visual Studio Code Remote WSL Extension

If you have ever wondered how to use the Windows Subsystem for Linux (WSL) as your full-time development environment right from VSCode, Visual Studio Code Remote WSL extension is the answer. It allows you to use a Linux-based environment, including the toolchains and utilities, and run and debug Linux-based applications from Windows. Sound good?

If you get the prompt shown in Figure 4-6 when you open your project in VSCode, go ahead and install it.
../images/488238_1_En_4_Chapter/488238_1_En_4_Fig6_HTML.jpg
Figure 4-6

Install Remote WSL

You can also install it from the Extensions page in VSCode, as shown in Figure 4-7.
../images/488238_1_En_4_Chapter/488238_1_En_4_Fig7_HTML.jpg
Figure 4-7

Install Remote WSL from the Extensions page

After the installation, reopen your VSCode. If you get a prompt saying that “Required assets are missing,” as in Figure 4-8, select Yes to add them.
../images/488238_1_En_4_Chapter/488238_1_En_4_Fig8_HTML.jpg
Figure 4-8

Required assets to build and debug

The project should already be opened in the VSCode, so we need to open it in WSL. To do that, press F1 and begin typing Remote-WSL: Reopen in WSL. As you type the words, the option should appear and you can select it. If the project is not opened in VSCode, you can directly open it in WSL by typing and selecting Remote-WSL: New Window Using Distro. See Figure 4-9.
../images/488238_1_En_4_Chapter/488238_1_En_4_Fig9_HTML.jpg
Figure 4-9

Reopen the folder in WSL

This will reopen the VSCode in WSL and you should see the indication in your VSCode, as shown in Figure 4-10.
../images/488238_1_En_4_Chapter/488238_1_En_4_Fig10_HTML.jpg
Figure 4-10

Editing on WSL Ubuntu

Rewriting the Application

In this section, we rewrite the Program.cs file to read the CPU temperature of the Raspberry Pi device. This is how your file will look.
using System;
using Iot.Device.CpuTemperature;
using System.Threading;
namespace raspberrypi.net.core
{
    class Program
    {
        private static CpuTemperature rpiCpuTemp = new CpuTemperature();
        static void Main(string[] args)
        {
            while (true)
            {
                if (rpiCpuTemp.IsAvailable)
                {
                    Console.WriteLine($"The CPU temperature at { DateTime.Now } is { rpiCpuTemp.Temperature.Celsius }");
                }
                Thread.Sleep(1000) ;
            }
        }
    }
}

Deploying the App to Raspberry Pi

The first thing to do is to make sure that your Raspberry Pi is switched on and connected to the Wi-Fi. We will be editing the launch.json file first. Let’s talk about that file now. It contains attributes such as name, type, and request. These are mandatory attributes of a launch.json file.

The Name Attribute

This attribute provides a meaningful name to your configuration. It’s found in the Debug launch configuration drop-down, as shown in Figure 4-11.
../images/488238_1_En_4_Chapter/488238_1_En_4_Fig11_HTML.jpg
Figure 4-11

Launch JSON name attribute

The Request Attribute

Currently (as of June 2020), request has two supported values—launch and attach. The easy way to explain the difference between launch and attach is to think of a launch configuration as a recipe for how to start your application in debug mode before VSCode attaches to it, while an attach configuration is a recipe for how to connect VSCode’s debugger to a process that is already running.

The Type Attribute

This attribute sets the type of debugger to use with this launch configuration. It depends on the environment. As you select an environment, each debug extension has a different type. For example, the node type is for the built-in node debugger.

Another important attribute in the launch.json file is preLaunchTask. This launches a task before the start of a debug session. We will define this task in the task.json file and use that task name here.

To deploy the application to Raspberry Pi, we must compile this application for Linux arm, and we can do that by configuring our VSCode. We do this configuration using the task.json file. Once we compile the application, we will copy our program to Raspberry Pi, using Rsync.

The Rsync Attribute

There are many ways that you can transfer your files from your computer to Raspberry Pi. Two popular ways are using SCP and Rsync. There are significant differences between those two. Let’s cover a few of them:
  • SCP stands for Secure Copy Protocol. It reads the source file and writes to the destination by performing a plain linear copy. Rsync also does the same, but with an efficient algorithm and a few optimizations that make the transfer faster.

  • Instead of just copying, Rsync will check for the file sizes and modification timestamps to make sure only changes or differences are copied. This makes the transfer a lot faster. It’s also easier to synchronize the files on the source and destination.

  • Rsync has an option for resuming the transfer if it is interrupted, whereas SCP doesn’t have this feature.

  • Last but not the least, according to OpenSSH developers on Wikipedia in 2019, the SCP protocol is outdated, and they recommend using modern protocols like Rsync.

Feel free to check out more about Rsync at https://rsync.samba.org/.

Let’s open our task.json file and update the code with Rsync. This file is responsible for the following jobs:
  • Compiling the application.

  • Copying the code to Raspberry Pi (yes, we use Rsync for this purpose).

Now you can edit the task.json file as follows.
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "RpiPublish",
            "command": "sh",
            "type": "shell",
            "problemMatcher": "$msCompile",
            "args": [
                "-c",
                ""dotnet publish -r linux-arm -c Debug -o ./bin/linux-arm/publish ./${workspaceFolderBasename}.csproj && rsync -rvuz ./bin/linux-arm/publish/ [email protected]:~/${workspaceFolderBasename}"",
            ]
        }
    ]
}

Here, RpiPublish is our task name and you might have noticed that we use the rsync -rvuz command. This copies the files from our computer to the Raspberry Pi.

Let’s use this task in the launch.json file now. The launch.json file is responsible for these jobs:
  • Calling the build tasks.

  • Asking Raspberry Pi to start the Visual Studio Code debugger.

  • Loading the application.

In the end, this is how your launch.json file will look.
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Rpi Publish and Debug",
            "type": "coreclr",
            "request": "launch",
            "preLaunchTask": "RpiPublish",
            "program": "~/${workspaceFolderBasename}/${workspaceFolderBasename}",
            "cwd": "~/${workspaceFolderBasename}",
            "stopAtEntry": false,
            "console": "internalConsole",
            "pipeTransport": {
                "pipeCwd": "${workspaceRoot}",
                "pipeProgram": "/usr/bin/ssh",
                "pipeArgs": [
                    "[email protected]"
                ],
                "debuggerPath": "~/vsdbg/vsdbg"
            }
        }
    ]
}

Note that I used [email protected] everywhere, because I am running WSL version 1. If you are running in Linux or using WSL2, you should change that to [email protected].

Variables in VSCode

You can see that we are using the ${workspaceRoot}, ${workspaceFolder}, and ${workspaceFolderBasename} variables in our task.json and launch.json files. These are VSCode’s predefined variables. The syntax to use them is ${variablename}. Some of the other variables are listed in Table 4-1.
Table 4-1

VSCode Variables

Variable Name

Description

${workspaceFolder}

The path of the folder opened in VSCode

${workspaceFolderBasename}

The name of the folder opened in VSCode without any slashes (/)

${file}

The current opened file

${relativeFile}

The current opened file relative to workspaceFolder

${relativeFileDirname}

The currently opened file’s dirname relative to workspaceFolder

${fileBasename}

The currently opened file’s basename

${fileBasenameNoExtension}

The currently opened file’s basename with no file extension

${fileDirname}

The currently opened file’s dirname

${fileExtname}

The currently opened file’s extension

${cwd}

The task runner’s current working directory on startup

${lineNumber}

The currently selected line number in the active file

${selectedText}

The currently selected text in the active file

${execPath}

The path to the running VSCode executable

${defaultBuildTask}

The name of the default build task

You can also create a new task to view the values of each variable. So let’s create a new task in the task.json file.
{
            "label": "Echo VSCode Variables",
            "type": "shell",
            "command": "echo ${workspaceRoot} | echo   ${workspaceFolder} |echo ${workspaceFolderBasename}"
}
Now press the F1 button and type Tasks: Run Task. Select the Echo VSCode Variables and the Continue Without Scanning the Output options. The variables’ values will appear in the terminal, as shown in Figure 4-12.
../images/488238_1_En_4_Chapter/488238_1_En_4_Fig12_HTML.jpg
Figure 4-12

Showing the VSCode variables

Debugging the App from Raspberry Pi

Keep in mind that you should install the ms-dotnettools.charp extension in your WSL too. See Figure 4-13.
../images/488238_1_En_4_Chapter/488238_1_En_4_Fig13_HTML.jpg
Figure 4-13

Install the ms-dotnettools extension

Now it’s time to run the application and deploy it to the Raspberry Pi. Click Run and add a breakpoint on any line you wish in Program.cs. Select the Rpi Publish and Debug configuration and then click the green icon on the left side of the configuration. See Figure 4-14.
../images/488238_1_En_4_Chapter/488238_1_En_4_Fig14_HTML.jpg
Figure 4-14

How to debug

Once you click the green icon, you will see a lot of things happening in the terminal. Figures 4-15 and 4-16 show the output of the debug session.
../images/488238_1_En_4_Chapter/488238_1_En_4_Fig15_HTML.jpg
Figure 4-15

The Debug window

../images/488238_1_En_4_Chapter/488238_1_En_4_Fig16_HTML.jpg
Figure 4-16

The Debug window console

Summary

Wow, that was amazing, right? In this chapter, you learned the following:
  • How to create a .NET Core application?

  • How to install Visual Studio Code Remote with the WSL extension?

  • How to read the CPU temperature of the Raspberry Pi device?

  • How to deploy the application to Raspberry Pi?

  • What Rsync is?

  • The variables in VSCode.

  • How to debug the application running in the Raspberry Pi device in VSCode?

Are you excited for the next chapter? I can’t wait to see you there.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.222.111.24