Raspberry piでc#開発する
Microsoftのdotnet coreはマルチプラットフォームなのでraspberryのようなlinuxでも開発実行ができます。 今回はc#の開発をraspberryでおこなった例です
手順
raspberry pi準備
raspberry piをすでにraspberry5まで来ているんですね。少し離れている間に高速になっています。
以前と違ってSDのフォーマットやdownloadなどを総合的に行うraspberry pi imagerというものがあるのでdownloadしましょう。
raspberry pi homeに行きます。
softwareに行って、少し下にimagerのダウンロードがありますので、ダウンロードします。imager_1.8.5.exe(2024/7/7現在)をダブルクリックしてインストールします。
起動するとこんな感じのラズベリー色のツールが立ち上がります
raspberry pi imagerでするべきこと
SDカード初期化
SDカードは8G程度あればいいのですが、初期化しないといけないので、次の処理をしてください。
raspberry pi imagerの真ん中のOSをクリックして「erase」を選択して、デバイスを選択して実行します。もしここでエラーが出たらそのSDは壊れているかもしれません。SDは消耗品だと思ってください。
OSダウンロード
imagerをダウンロードしたところの下のほうに「see all download options」があります。
32bit,64bitが分かれて置いてありますので選んでください。今回は、64bitを選びました。
1.1Gあるので時間がかかります。ダウンロードする時にユーザー名など聞かれますがこの時のユーザー名がリモートなどでログインする時のユーザー名になります。以前はデフォルトがpiでした。
SDカード書き込み
imagerのosで「custom」を選びます。ここでどれかOSを選んでもいいのですが、毎回やるのは面倒なので、先にDOWNLOADしたものを使いました。
書き込んだら、続いてチェックが走りますのでそれが終わるまで待ってください。
書き込み終わったら、初期化しろとか色々OSが言うかもしれませんが無視してSDを取り外してください
raspberry pi電源投入
USBキーボード、USBマウス、HDMIケーブルをつなぎ、SDカードを入れて、ディスプレイの準備ができたらUSB Bタイプの電源を入れて起動しましょう。
最初の起動はディスプレイがある状態でしましょう。rasberry configurationで設定画面を開いて日本語やパスワードの設定をしましょう。
設定が出来たら右上のWiFiのアイコンにポイントしてIPアドレスを調べておいてください。ポイントはマウスをかざすだけで、クリックしてはいけません。おそらくそのIPアドレスでしばらく接続することになるでしょう。
リモート接続
ディスプレイを別に用意できる人は良いですが、そうでない方はリモート接続すればパソコンの中に画面を表示して操作ができるので楽ができます。
設定のインターフェースで「SSH」と「VNC」をONにしてください。この後「REBOOT」すると、リモートが出来るようになります。
続いて、リモートアクセス用のアプリをWindowsにインストールします。画面が出るのがReal VNC Viewerで、コマンドでのやり取りが teraTermです。
real vnc viewerのダウンロードでWindowsのものをダウンロードしてインストールしてください。起動したらIPアドレスを聞かれます
ここでは半角数値で192.168.12.191と入力しています。
ユーザー名はdownloadするときに決めたものです。パスワードもそうですが、後から変えたのであればそちらを入れてください
するとWindowとしてVNCが立ち上がり、その中にraspberryの画面が表示されます。Windowsのマウスをこの中で移動させれば実際の画面でもマウスが移動します。
shutdownしないでただ接続を切りたい場合はマウスを上に持って行って、真ん中のせり出しメニューの×を押してください。
shutdownしたい場合はログアウトからshutdownしてください。
接続が切れて黒い画面になるのでアプリを終了してください。ただし、shutdown自体には時間が掛かりますので、raspberry本体の緑のLEDのチカチカが止まってから 電源を抜いてください。
画面は不要で、コマンドだけで良い場合は、teratermなどのsshアプリを使用します。
tera termは日本人が作ったアプリで、暗号化通信ができるのでよく使われます。窓の杜などからダウンロードしましょう。
ダウンロード、インストールしたら起動します
起動したらIPアドレスを入力します。初回だけ暗号化の確認画面がでますので確認してください。
ユーザーIDとパスフレーズを入れます。初回で入れたパスワードです。これでコマンド入力が出来ます。
dotnet 準備
ようやくここまで来ました。ここからdotnetの話になります。このあたりからはMicrosoft Learn にも載っています。くわしく載っています
次のコマンドを入力してください
curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --channel STS
少し時間が掛かりますが、自動的にインストールが行われます。つづけて設定があります
echo 'export DOTNET_ROOT=$HOME/.dotnet' >> ~/.bashrc echo 'export PATH=$PATH:$HOME/.dotnet' >> ~/.bashrc source ~/.bashrc dotnet --version
コンソールアプリ
ようやく環境が出来ましたので、teratermでつないでコンソールアプリでhello worldしてみましょう。
mkdir cstest cd cstest
まずはこれからworkspaceになるcstestフォルダーを作ってその下に作っていきます
f710@ras01:~/cstest $ dotnet new console -o HelloCon テンプレート "コンソール アプリ" が正常に作成されました。 作成後の操作を処理しています... /home/f710/cstest/HelloCon/HelloCon.csproj を復元しています: Determining projects to restore... /home/f710/cstest/HelloCon/HelloCon.csproj を復元しました (720 ミリ秒)。 正常に復元されました。
これですでにひな形は出来ていますが、少し変更してみましょう
f710@ras01:~/cstest $ cd HelloCon f710@ras01:~/cstest/HelloCon $ ls HelloCon.csproj Program.cs obj f710@ras01:~/cstest/HelloCon $ sudo nano Program.cs
nanoがlinuxのエディタで、少し使いづらいですが、viよりましです。
sudoは特権を持って実行でProgram.csがメインプログラムです
C#の最上位レベルのコーディングになっているのでmainの内部だけのソースです。
Hello worldをHello console worldに変更して、CTRL+X y Enter で変更保存します。
f710@ras01:~/cstest/HelloCon $ dotnet run Hello, console World!
実は最初の1回目だけテレメトリとか開発証明書の発行とかが表示されます。raspberryでc#の実行ができました。
dotnet runはビルドしてrunです。実行だけするのであれば、
f710@ras01:~/cstest/HelloCon $ bin/Debug/net7.0/HelloCon Hello, console World!
で、実行できます。
webでHello world
workspaceになるcstestフォルダーに移動してその下に作っていきます
f710@ras01:~/cstest $ dotnet new web -o HelloWeb テンプレート "ASP.NET Core (空)" が正常に作成されました。 作成後の操作を処理しています... /home/f710/cstest/HelloWeb/HelloWeb.csproj を復元しています: Determining projects to restore... /home/f710/cstest/HelloWeb/HelloWeb.csproj を復元しました (704 ミリ秒)。
これですでにひな形は出来ていますが、少し変更してみましょう
f710@ras01:~/cstest $ cd HelloWeb f710@ras01:~/cstest/HelloWeb $ ls HelloWeb.csproj Properties appsettings.json Program.cs appsettings.Development.json obj f710@ras01:~/cstest/HelloWeb $ sudo nano Program.cs
WebApplicationのCreateBuilderメソッドでWebApplicationBuilderクラスを作成します。
MapGetでどのurlの時に機能を呼び出すのかを記述します。今回はHelo worldの文字を出力します
f710@ras01:~/cstest/HelloWeb $ sudo nano Properties/launchSettings.json
実はdefaultでrunしてしまうと、localhostで実行されてしまい、外からアクセスできないので、Settingを変えます
httpのapplicationUrlをlocalhostから0.0.0.0に変えてください。
プログラムを起動すると指定されたportで待ち受けてくれるので、接続します。ちなみにport番号は適当です。ぶつかっていなければ何番でもかまいません。
f710@ras01:~/cstest/HelloWeb $ dotnet run ビルドしています... info: Microsoft.Hosting.Lifetime[14] Now listening on: http://0.0.0.0:5003 info: Microsoft.Hosting.Lifetime[0] Application started. Press Ctrl+C to shut down. info: Microsoft.Hosting.Lifetime[0] Hosting environment: Development info: Microsoft.Hosting.Lifetime[0] Content root path: /home/f710/cstest/HelloWeb
ブラウザを立ち上げて、接続します
文字が出ただけですが、Webに接続できました。
ところで、このc#はIISを使用していません。kestrelという簡易サーバーです。
^Cinfo: Microsoft.Hosting.Lifetime[0] Application is shutting down...
kestrelを止めるにはCTRL+Cを押します
webで文字としてhtml出力
workspaceになるcstestフォルダーに移動してその下に作っていきます
f710@ras01:~/cstest $ dotnet new web -o HelloHtml テンプレート "ASP.NET Core (空)" が正常に作成されました。 作成後の操作を処理しています... /home/f710/cstest/HelloHtml/HelloHtml.csproj を復元しています: Determining projects to restore... /home/f710/cstest/HelloHtml/HelloHtml.csproj を復元しました (782 ミリ秒)。 正常に復元されました。
さっきはただ文字列を出しましたが、今度は文字列としてHTMLを出してみましょう。先ほどと同じソースなのでこんな風に変更します
var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.MapGet("/", (HttpContext context) => { context.Response.ContentType = "text/html"; return """ <html><head> <title>Hello</title> </head> <body> <h1>Hello</h1> <p>This is sample page.</p> </body> </hetml> """; } ); app.Run();
applicationUrlも変更して実行します。
Razorテンプレートのサンプル
workspaceになるcstestフォルダーに移動してその下に作っていきます
f710@ras01:~/cstest $ dotnet new webapp -o HelloRazor テンプレート "ASP.NET Core Web アプリ" が正常に作成されました。 このテンプレートには、Microsoft 以外のパーティのテクノロジーが含まれています。詳しくは、https://aka.ms/aspnetcore/7.0-third-party-notices をご覧ください。 作成後の操作を処理しています... /home/f710/cstest/HelloRazor/HelloRazor.csproj を復元しています: Determining projects to restore... /home/f710/cstest/HelloRazor/HelloRazor.csproj を復元しました (709 ミリ秒)。 正常に復元されました。
Razorは1ページ単位に2つのファイルを組み合わせて作成するアプリケーションです。 *.cshtmlというテンプレートの部分とそれに対応する *.cshtml.csというコードの部分がPagesフォルダーにあることで作動します。
f710@ras01:~/cstest/HelloRazor $ ls Pages Error.cshtml Index.cshtml.cs Shared Error.cshtml.cs Privacy.cshtml _ViewImports.cshtml Index.cshtml Privacy.cshtml.cs _ViewStart.cshtml
Error,Index,Privacyの3つのページができています。
applicationUrlだけ変更して実行すると、こんな感じの出力になります。bootstrapが効いています
ソースを眺めてみましょう。
var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddRazorPages(); var app = builder.Build(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.MapRazorPages(); app.Run();
同じWebAplicationで始まっていますが、色々なミドルウェアが追加されています。リダイレクトをつかさどるもの、wwwrootなどの静的ファイルの対応、Pagesフォルダーの中のファイルにアクセスする仕組み、認証機能などです。
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; namespace HelloRazor.Pages; public class IndexModel : PageModel { private readonly ILogger_logger; public IndexModel(ILogger logger) { _logger = logger; } public void OnGet() { } }
IndexModelというクラスができています。それぞれのファイルが*Modelという名前が付いたクラスになります。
OnGet関数の中にGetが発生したときに行う処理を書きます
@page @model IndexModel @{ ViewData["Title"] = "Home page"; } <div class="text-center"> <h1 class="display-4">Welcome</h1> <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p> </div>
先ほどのcsファイルのモデルを使用しています。@pageで始まっています。これがRazorディレクトティブでRazorであることを宣言しています。
classの中に display-4とかあるのは frameworkのbootstarp形式です。これらを組み合わせてRazorの画面を作っています。