GMO DevelopersDay
GMO DevelopersDay
2024.11.29Fri - 11.30Sat YouTube Live
イベント開催まであと6

GMOバーチャルジムを革新!WindowsPCからRaspberry Pi 4への移行事例紹介

今回は、GMOバーチャルジムで稼働しているWindows PCを RaspberryPi4に移行する作業、おもにトレッドミルコントローラという .NET Framework 4.6 プログラムの移植作業についてご紹介します

GMOバーチャルジムとは?

GMOインターネットグループが開発した【GMOバーチャルジム】は、180°全面ディスプレイに各大会のコースの映像を流しながら走ることで実際にレースを走っている感覚を味わうことが出来るトレーニングマシンです
コース合わせてトレッドミルの傾斜が自動で調整され、気温・風・酸素濃度も自由に設定することができることから、大会前のコースの試走や、低酸素トレーニングに活用されていますhttps://athletes.gmo.jp/about/ より

今回は、このシステムで利用しているPCの入れ替え時期が近くなったため、WindowsPCから RaspberryPi4に移行することにしました

WindowsPCで動いているもの

今回移行の対象となった WindowsPCでは 以下のものがうごいていました
トレッドミルコントローラ (今回の記事の対象です)

  • トレッドミルの管理を行っています
  • Windowsサービスとして動いています

マネージャーサイト

  • 設備の予約管理や、トレーニングの履歴管理等、設備全体の管理を行っているWebサイトです
  • Dockerのコンテナとして動いています

監視ツール

  • 各種機器の監視をし正常に動作しているかのチェックを行っています
  • Dockerのコンテナとして動いています

Windowsから移行するにあたり トレッドミルコントローラが移行の主なハードルになっていました

トレッドミルコントローラで行っていること

  • USBシリアル変換ケーブルを用いたシリアル通信でトレッドミルの制御
  • HTTP Serverでマネージャーサイトからのコマンドの受付
  • UDPでマネージャサイトや他の機器にトレッドミルの情報の送信

なんでRaspberryPi4?

WindowsPCはWindows Update等で設定が変わってしまうことがあり、メンテナンス作業に時間がかかってしまっていました
Raspberry Pi4 は メモリも増えて早くなり、USBのSSDを接続すればSDカードの寿命からも開放され普通のLinuxマシンとして利用できます、最近はARMのバイナリも豊富になり昔より自分でビルドをする必要も減っています

また 昔は手動で行っていた OverlayFSをつかってSDカードを読み取り専用にする等の小技は今のRaspberry Pi OS では標準でサーポートされ簡単に設定できるようになっています

Type-Cコネクタを利用したOTGでPCから給電しつつPCとネットワーク接続が可能です、PC側でテザリングの設定を行うとRaspberryPiからPCを経由してインターネット接続をしたり、RaspbeeryPiでトンネル接続を作成してPCからそのトンネル経由で接続する等も可能です
開発時はUSBケーブル1本で開発を行っていました。別途電源を用意したりする必要もLANケーブルも必要なく気軽に使えます

Raspberry Pi 5ではなく4にしたのは、単純にRaspberry Pi 5の発売前に調達したためです。今でもRaspberyPi4にするかもしれないです、5は熱いので…

移行開始時点では、私のC#の経験はUnityで使っていた程度で、 .NET Framework や .NET Coreを十分に理解していなかったため、まず .NET Framework を Linuxで動かすための調査から始めました

そこで 4.6等も含めてリリース年ごとに並べました

.NET VersionRelease Year機能強化と新機能
.NET Framework 4.02010並列コンピューティング
Managed Extensibility Framework
アプリケーションの互換性と配置
.NET Framework 4.52012非同期のファイル操作
Windows 8.x ストア アプリ用 .NET
.NET Framework 4.62015マネージド コードの JIT コンパイラ (64 ビット)
ASP.NET Core
.NET Core 1.02016マルチプラットフォームサポート
オープンソース
.NET Framework 4.72017楕円曲線暗号 (ECC) による機能強化
高 DPI のサポート
オブジェクト キャッシュの拡張性
.NET Core 2.02017.NET Standard 2.0 のサポート
.NET Framework 4.82019ZLib の更新バージョンの使用
ServiceHealthBehavior の導入
JIT コンパイラの機能強化
.NET Core 3.02019Windows デスクトップ アプリケーションのサポート
.NET 5.02020パフォーマンスの向上
ダンプ デバッグでのツールのサポート
.NET 6.02021Arm64 のサポート
長期サポート (LTS)
.NET 7.02022パフォーマンス
ジェネリック型数値演算

.NET Coreと.NET Framework 4.6以降が同じようなタイミングでリリースされてることがわかります。
.NET CoreはWindows以外の環境でも動くようにしたマイクロソフトによるクロスプラットフォームかつオープンソースのリファレンス実装ということで、同時期にリリースされた .NET Frameworkとある程度の互換性が保たれているようでした

.NET Core 4 が存在せず、.NET 5 になっているのは .NET Framework 4.x との混同を避けるためにスキップされました

というわけで、移植するだけならば .NET Framework 4.6から .NET Core 1.0がバージョンが近いので楽そうですが、2019年6月27日にサポートが終了しています

ちょうど実装を始めたころに .NET 8がリリースされたので それを使うことにしました

.NET Framework 4.6から.NET 8へのアップグレードでおよそ8年分いきなり新しくすることになりました
.NET 8がLinxuでシリアルポートを扱えない場合は移行が不可能になりますが少し調べただけでも使えるということがわかり割と互換性は担保されているようです

RaspberryPiはuartを持っています、また今使っているUSBシリアル変換ケーブルもそのまま動くことが期待できます。現在の配線をそのまま利用したいので、USBシリアル変換ケーブルを利用することにしました

移植作業

今回の移行では.NET8にすると同時にコンテナ化して、Dockerで動かすことにしました
コンテナ化も .NETの標準機能で簡単に行えました Dockerfileを自分で用意する必要もないです

実際の移植作業ですが、プロジェクトファイルを新規で作成することにしました
.NET8のプロジェクトを作成してビルドを行うといくつかのエラーが出ましたが、想像していたよりもエラーが少なくてびっくりしました

主なエラーの内容は以下の3つです
– Windowsサービス等Windowsの機能に依存しているもの
– インスタンスのDeepCopyで利用していた BinaryFormatterが非推奨に
– 外部ライブラリが足りない

外部ライブラリのインストールやエラーの書き直しを行いながらビルドを行います
エラーがなくなりビルドが成功するまでくりかえしますが、過去に行った移植作業等と比べても難しいものではありませんでした

同時にコンテナ化に伴う修正としてLog4netの出力先を標準出力に変更しました
ConfigurationTransformで設定ファイルをビルド時に書き換えていたのを環境変数を参照するようにも変更しています

公式のドキュメントが見やすく整備されているので特にトラブルに遭遇することなくエラーの解消や変更点の実装が行えました

利用しているライブラリは以下になりました

Dynamic.Json 1.4.0 1.4.0
log4net 2.0.15 2.0.15
Microsoft.Extensions.Configuration 8.0.0 8.0.0
Microsoft.Extensions.Configuration.CommandLine 8.0.0 8.0.0
Microsoft.Extensions.Configuration.EnvironmentVariables 8.0.0 8.0.0
Microsoft.Extensions.Configuration.FileExtensions 8.0.0 8.0.0
Microsoft.Extensions.Configuration.Json 8.0.0 8.0.0
Microsoft.Extensions.Hosting 8.0.0 8.0.0
Microsoft.Extensions.Hosting.Abstractions 8.0.0 8.0.0
Microsoft.NET.Build.Containers 8.0.200 8.0.200
Microsoft.Windows.Compatibility 8.0.0 8.0.0
System.Text.Encoding.CodePages 8.0.0 8.0.0

動作確認

トレッドミルが無いと動作確認できないのでデバッグ等は現地で行っています

起動や、マネージャーサイトとの疎通等は問題ありませんでしたが、トレーニングを開始したところシリアル通信がうまく行っていないようでトレッドミルが動かない状態でした
トレッドミルとの通信は iso 2022-jp を利用しており文字コードの変換が失敗しているようでした

テキストエンコードは以下に詳細があり、 .NET5以降はサポートにチェックが入っていませんでした
https://learn.microsoft.com/ja-jp/dotnet/fundamentals/runtime-libraries/system-text-encoding

NuGetパッケージ<System.Text.Encoding.CodePages>を追加すればShift JIS 等を利用できることがわかり
パッケージの追加と以下の1行をソースコードに追加で対処が可能なようです

Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

この変更で問題なく動作するようになりました。
無事 .NET Framework 4.6からLinuxの .NET 8へと移行することができました。
コマンドを投げるとトレッドミルの傾斜が変わったり速度が変わったりするのは楽しかったです

おまけ:Raspberry4 のUART

RaspberryPi4 では 6つのUARTを持っています、RaspberryPi3/Zero等その他のシリーズは2つのUARTを持っています
使う時に注意が必要なmini UARTのuart0/1は以外の空いているUARTを利用することができますがI2CやSPIとピンが競合しています
UARTとGPIOピンの関係は以下のようになっていました

UARTGPIOピン番号tty
uart0GPIO 14,15 
32,33 or 36,37
/dev/ttyAMA0
uart1GPIO
14,15 32,33 or 36,37
/dev/ttyS0
uart2GPIO 0,1 (default off)/dev/ttyAMA2
uart3GPIO 4,5 (default off)/dev/ttyAMA3
uart4GPIO 8,9 (default off)/dev/ttyAMA4
uart5GPIO 12,13 (default off)/dev/ttyAMA5
pinoutコマンドの結果

ブログの著者欄

大山 仁

GMOインターネットグループ株式会社

アプリケーション開発本部 DX推進開発部 ビジネスサポートプロダクトチーム所属

採用情報

関連記事

KEYWORD

採用情報

SNS FOLLOW

GMOインターネットグループのSNSをフォローして最新情報をチェック