Visual Studio 2022 C# でIOT（RaspberryPi でＬチカ）

Visual Studio C# でラズパイ上のデバイスが動かせるというのでやってみた。
調べてみるとC#でラズパイ上でLチカする記事や動画は散見するが情報が古るいのが多く、紆余曲折して「Visual Studio2022」で動くようになるまで中々時間がかかった。（私だけ？）
原因の多くは、およそ６年ぶりのC#と言うこともあり不慣れなことだったのですが、Visual Studioの歴史は長く、多くのフレームワークが存在するため、何を選んだら良いかの理解ができるまで時間がかかったということです。
（出て来る用語も良く分からん！！）
そこで、自分自身の備忘録も含めて、とりあえず「Visual Studio 2022」上のC#を使ってラズパイ上でLチカするための手順をまとめてみました。
やり方は幾つかあるようなのですが、以下は一つの例です。（一番簡単な方法かと思いますが？）
## 準備

- PC
    - OS　：　Windows 10
    - Visual Studio　：　2022
- Raspverry Pi4
    - Rasbian GNU/Linux 10 (Buster)
    - SambaやVNCなどのリモートアクセス環境
    - LEDなどは以下のように結線しておくこと

        この例では、GPIO 23、24、25を使っています。
        ※ LEDは順番に点灯しますが、GPIOピンから流せる電流はトータルで50mA程度なので、それに合わせた抵抗値を選定。

![fig0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3287420/8a81b841-2d64-d4ec-117b-6ee3d19e0e5c.png)

## 大まかな流れ
マイクロソフトサイトの「[.NET IoT ライブラリを使用して IoT デバイス用のアプリを開発する](https://learn.microsoft.com/ja-jp/dotnet/iot/intro)」を良く読めば分かる事なのでしょうが、全体像をつかめない状態では混乱します。
方法は幾つかあるようですが、ここでは以下の流れにより実現しています。

1. ラズパイには「dotnet」関係ファイルのインストールはしません。
1. PC（私の場合Windows10)で Visual Studio 2022 を起動
1. プロジェクトの作成（名称入力／フレームワーク選択）
1. .NET IoTライブラリの選択／インストール
1. コード入力
1. ビルド
1. 発行条件入力
1. 発行（ラズパイに転送）
1. ラズパイ上で動作確認

## 手順
 Visual Studio 2022を起動

- 「新しいプロジェクトの作成(N)」を選択します。
![fig1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3287420/a3748c8c-7c77-ffb8-9a41-0f29216e5343.png)
- 「コンソールアプリ」、「次へ(N)」を選択。
![fig2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3287420/ccaa5959-635b-3fc8-9375-8b7fe662760c.png)
- 「プロジェクト名」を入力して「次へ(N)」を選択。（ここでは、「BlinkLED」とした）
![fig3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3287420/9264bb45-8f57-2c9b-540a-7e73add8f87e.png)
- 「フレームワーク」を「.NET 7.0」とし「作成(C)」を選択。
※ インストールした環境により出て来る項目が多少違うかも知れません。 
![fig4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3287420/6076dacb-fdd4-21cb-f54c-e33a1b17bae4.png)
- Visual Studio 2022 のIDE画面となり、デフォルトサンプルが表示されます。
![fig5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3287420/7d13b9cd-4a2a-092d-a60e-f1c6f739d949.png)
- サンプルソースコードはとりあえず無視して、GPIOライブラリをインストールします。
画面右の「ソリューション名」（この場合「BlinkLED」）を右ボタンクリックして「NuGetパッケージ管理(N)...」を選択します。
![fig6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3287420/e472f8a3-f9f6-851b-9b72-cf12627b2b20.png)
- 「参照」タブから「System.Device.GPIO」を検索します。
![fig7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3287420/06bf67b5-2315-6aa9-2f68-e7ae984a9d6e.png)
- 「インストール」ボタンを押します。
![fig8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3287420/c2cea428-c41c-15a5-0341-d5a5fc93b0b3.png)
- 「変更のプレビュー」で「OK」ボタンを押します。
![fig9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3287420/5b5032b2-ce8e-e6da-cfd2-5430d778828c.png)
- 「ライセンスへの同意」で「I Accept」ボタンを押します。
![fig10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3287420/a1cad7c2-8f9d-1887-2ddc-9e613ffbd82e.png)
- 「Program.cs」タブで、サンプルコードを以下のものに置き換えます。
プログラムは単純なのでポート番号などが異なる場合は、設置したハード環境に合わせて修正願います。
![fig11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3287420/12a7ad03-a960-d1a9-18e9-ddf441b9f4d8.png)
```
using System;
using System.Device.Gpio;
using System.Threading;

namespace BlinkLED
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, World!");

            int pin23 = 23;
            int pin24 = 24;
            int pin25 = 25;

            GpioController gpio = new GpioController();

            gpio.OpenPin(pin23, PinMode.Output);
            gpio.OpenPin(pin24, PinMode.Output);
            gpio.OpenPin(pin25, PinMode.Output);

            while (true)
            {
                gpio.Write(pin23, PinValue.High);
                gpio.Write(pin24, PinValue.Low);
                gpio.Write(pin25, PinValue.Low);
                Thread.Sleep(150);

                gpio.Write(pin23, PinValue.Low);
                gpio.Write(pin24, PinValue.High);
                gpio.Write(pin25, PinValue.Low);
                Thread.Sleep(150);

                gpio.Write(pin23, PinValue.Low);
                gpio.Write(pin24, PinValue.Low);
                gpio.Write(pin25, PinValue.High);
                Thread.Sleep(150);
            }
        }
    }
}
```
- 「ソリューションのビルド(B)」を選択します。
画面下の出力で、エラーが無ければビルドは成功です。
![fig12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3287420/23263eac-0fde-cbaf-a8ea-b1e4fac8525f.png)
- 画面右のプロジェクト名で右ボタンを押して、「発行(B)」を選択します。
![fig13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3287420/fa688b9c-36b5-c34e-1c69-09029086c288.png)
- 中央の鉛筆のようなアイコン（どれでも同じ）を押します。
![fig14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3287420/a9dc9690-e1b2-74d6-ed71-cc4286a7e9c4.png)
- 各項目は図のように選択指定します。
    - 構成　：　Release | Any CPU
    - ターゲットフレームワーク　：　net7.0
    - 配置モード　：　自己完結
    - ターゲットランタイム　：　linux-arm
    - ターゲット場所　：　ラズパイの保存場所を参照指定
![fig15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3287420/22a62f14-a469-feef-a9b9-075c92818f1a.png)
- 「発行」ボタンを押します。
![fig16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3287420/a6e38c2c-3fd3-d103-2a4c-367ddd2ad37c.png)
- 無事ラズパイに転送されたことを確認します。
※「自己完結型」なので、必要なファイルが全て転送されますので、転送が完了するまで時間が掛かります。
また、今回の例のようにLEDを点灯させるためだけでも約65MBあります。
![fig17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3287420/cbf57215-4014-86a4-392c-a4cb5b5418eb.png)

## 動作確認
ラズパイで転送されたフォルダに移動し、コマンドラインで
```
./BlinkLED
```
と入力します。
　　![fig18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3287420/f4be6b30-6792-f95c-ba70-26bcdf51711b.png)
　　![fig19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3287420/b4176295-cd87-45ec-81e4-44ff3996295f.png)

## あとがき
Microsoftの「[.NET の IoT ライブラリのドキュメント](https://learn.microsoft.com/ja-jp/dotnet/iot/)」は、読んでも余りにも多岐にわたるので今でも良く分かりません。
とりあえず、上記のような方法で動かしてから、先のドキュメント類を読むと理解が進むようです。
現在のところ、C#が対応しているデバイスは、
「[使用可能なデバイスバインドの完全な一覧](https://github.com/dotnet/iot/blob/main/src/devices/README.md)」
で確認できます。
同じデバイスでも、Net上の古い情報ではコンパイルも出来なかったので、先のサイトのサンプルで確認することをお勧めします。

でもなぁ、個人的にはラズパイ上のデバイスを動かすならラズパイ上のPythonで十分だし、C#で動かす必要性が感じられないが？？

むしろ、PC（C#）を司令塔（データ収集／分析／・・）にして、
　　　PC　<--- 通信 --->　入出力（ラズパイ／Arduino／ESP／・・・）
の通信部分を強化（簡素化）する方が良いのではないか？？