Skip to content

Commit

Permalink
update posts
Browse files Browse the repository at this point in the history
  • Loading branch information
mnishiguchi committed Dec 9, 2024
1 parent 599df9a commit 7207cb9
Show file tree
Hide file tree
Showing 4 changed files with 375 additions and 11 deletions.
196 changes: 196 additions & 0 deletions public/20241208-elixir-port-interface.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
---
title: Elixir Port を使って C 言語プログラムと連携する
tags:
- C
- port
- Elixir
- IoT
- Nerves
private: false
updated_at: '2024-12-08T21:41:38+09:00'
id: 6e0c486cd5907348d321
organization_url_name: fukuokaex
slide: false
ignorePublish: false
---


## はじめに

Elixir の [Port](https://hexdocs.pm/elixir/Port.html) を使うと、C 言語などで書かれた外部プログラムと連携できます。
ただ、どこから手をつければいいのか、全体の構成が掴みにくいことがありますよね。

この記事では、Port を使ったプロジェクトの基本構成を学べるように、次の 2 つのプロジェクトを例に解説します。

1. **[Blinkchain](https://github.com/GregMefford/blinkchain)**: LED 制御ライブラリで、Port を活用したベストプラクティスの学びが得られます。
2. **[elixir-sensors/sgp40](https://github.com/elixir-sensors/sgp40)**: Blinkchain の構成を参考にして実装した空気質センサーライブラリ。

Port を用いたプロジェクトの全体像を理解し、自分のアイデアに応用できる内容を目指します。

## Blinkchain とは

**Blinkchain** は、Elixir を使って LED ストリップ(WS2812B など)を制御するライブラリです。
内部では Port を利用して C 言語コードを呼び出し、高速でハードウェア制御を行っています。

## Blinkchain の学びが役立った点

1. **ディレクトリ構成の整理**:

- `c_src/` ディレクトリで C プログラムを管理し、Makefile を活用したビルドフローを導入。

2. **Port 通信の抽象化**:

- Port を専用モジュールで管理し、Elixir 側からは API を通じて簡単に操作できる構造を採用。

3. **明確な公開 API の設計**:
- ユーザー向けの操作をシンプルにし、利用者が内部の複雑さを意識せずに使えるように設計。


## Blinkchain のディレクトリ構成

```plaintext
blinkchain/
├── c_src/ # **C プログラムのソースコードを格納**
│ └── port_interface.c # **LED 制御ロジック**
├── lib/
│ ├── blinkchain.ex # **公開 API**
│ └── blinkchain/ # **内部ロジックをモジュール化**
│ └── port.ex # **Port 通信の管理**
├── test/
│ └── blinkchain_test.exs # **テストコード**
├── Makefile # **C プログラムのビルド設定**
├── mix.exs # プロジェクト設定
└── README.md # プロジェクトのドキュメント
```

## Blinkchain の各ファイルの役割と実装例

### C プログラム(`c_src/port_interface.c`

以下は、標準入力で受け取ったコマンドを元に LED を制御する C プログラムの簡略化版です。

```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
char command[256];
while (fgets(command, sizeof(command), stdin)) {
if (strcmp(command, "turn_on") == 0) {
printf("LED turned on");
} else if (strcmp(command, "turn_off") == 0) {
printf("LED turned off");
} else {
printf("Unknown command");
}
fflush(stdout);
}
return 0;
}
```

### Makefile(`Makefile`

C プログラムを簡単にコンパイルできるように Makefile を用意します。

```makefile
all:
gcc -o port_interface c_src/port_interface.c
```

`make` コマンドを実行することで、`port_interface` バイナリが生成されます。

### Port 管理モジュール(`lib/blinkchain/port.ex`)

Port を管理する Elixir モジュールです。

```elixir
defmodule Blinkchain.Port do
def send_command(command) do
port = Port.open({:spawn, "./port_interface"}, [:binary])

send(port, {self(), {:command, "#{command}"}})

receive do
{^port, {:data, response}} -> String.trim(response)
after
5000 -> "Timeout"
end
end
end
```

### 公開 API(`lib/blinkchain.ex`

ライブラリ利用者向けのシンプルな API を提供します。

```elixir
defmodule Blinkchain do
alias Blinkchain.Port

def turn_on do
Port.send_command("turn_on")
end

def turn_off do
Port.send_command("turn_off")
end
end
```

### テストコード(`test/blinkchain_test.exs`

```elixir
defmodule BlinkchainTest do
use ExUnit.Case
alias Blinkchain

test "turns on the LED" do
assert Blinkchain.turn_on() == "LED turned on"
end

test "turns off the LED" do
assert Blinkchain.turn_off() == "LED turned off"
end
end
```

## elixir-sensors/sgp40 プロジェクトでの応用

Blinkchain で学んだ構成や実装パターンを元に、私のプロジェクト **[elixir-sensors/sgp40](https://github.com/elixir-sensors/sgp40)** では、空気質センサー SGP40 のデータを Elixir で取得する仕組みを構築しました。

```plaintext
sgp40/
├── c_src/ # **C プログラムのソースコードを格納**
│ └── sgp40.c # **センサー制御ロジック**
├── lib/
│ ├── sgp40.ex # **公開 API**
│ └── sgp40/ # **内部ロジックをモジュール化**
│ └── port.ex # **Port 通信の管理**
├── test/
│ └── sgp40_test.exs # **テストコード**
├── Makefile # **C プログラムのビルド設定**
├── mix.exs # プロジェクト設定
└── README.md # プロジェクトのドキュメント
```

:tada: :tada: :tada:

## おわりに

この記事では、Elixir の Port を使って C 言語プログラムと連携する方法を解説しました。

Port を活用した連携は、ハードウェアや外部プログラムを操作する際に非常に強力です。ぜひ、この記事を参考に、自分のプロジェクトに取り入れてみてください!

何か氣づいた点や改善提案があれば、コメントで共有していただけると嬉しいです!

![toukon-qiita-macbook_20230912_091808.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82804/fd5c55ec-4fe0-8af6-59bc-bab1ef3d182b.jpeg)

## 関連リンク

- [Blinkchain GitHub リポジトリ](https://github.com/GregMefford/blinkchain)
- [elixir-sensors/sgp40 GitHub リポジトリ](https://github.com/elixir-sensors/sgp40)
- [Elixir Port 公式ドキュメント](https://hexdocs.pm/elixir/Port.html)
- [elixir_make](https://github.com/elixir-lang/elixir_make)

15 changes: 4 additions & 11 deletions public/20241208-nerves-external-commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ tags:
- IoT
- Nerves
private: false
updated_at: '2024-12-08T19:55:17+09:00'
updated_at: '2024-12-08T20:31:32+09:00'
id: 2ce8385203de5434e06d
organization_url_name: fukuokaex
slide: false
Expand Down Expand Up @@ -111,16 +111,9 @@ File.cp_r!("/source_dir", "/target_dir")

プロセス制御が必要な場面で活用します。SIGKILL 遅延やプロセス名の設定をカスタマイズできるため、高度な要件を持つアプリケーションに向いています。

#### 実例: 高度なプロセス制御
`Nerves.Port` を使用する場合は、`priv/port` バイナリがファームウェアに含まれている必要があります。しかしながら、このバイナリはデフォルトでは含まれておらず、NervesのIExで実行しようとしてもうまく行きません。

```elixir
Nerves.Port.cmd("ls", ["-la"], delay_to_sigkill: 5, arg0: "list_files")
```

このコードは以下を実現します:

- **`delay_to_sigkill`**: SIGKILL を送信する前に 5 秒の待機を設定。
- **`arg0`**: 外部プロセスにカスタムプロセス名 "list_files" を設定。
実は具体的のどういうときにこれが使われるのかよくわかっていません。詳しい方がいらしたらぜひ教えてください!

:::note info
`Nerves.Port` は、内部で [MuonTrap](https://github.com/fhunleth/muontrap) から移植されたコードを一部使用しています。MuonTrap は、Nerves 環境におけるプロセス管理を強化するためのツールで、プロセス制御の柔軟性を高めるための設計がなされています。
Expand All @@ -143,7 +136,7 @@ Nerves.Port.cmd("ls", ["-la"], delay_to_sigkill: 5, arg0: "list_files")
<!--- begin-reusable-links --->

[nerves-runtime-cmd3]: https://hexdocs.pm/nerves_runtime/Nerves.Runtime.html#cmd/3
[nerves-port-docs]: https://hexdocs.pm/nerves_runtime/Nerves.Runtime.html#module-ports
[nerves-port-docs]: https://hexdocs.pm/nerves/Nerves.Port.html
[system-cmd3]: https://hexdocs.pm/elixir/System.html#cmd/3
[file-docs]: https://hexdocs.pm/elixir/File.html
[nerves-runtime-docs]: https://hexdocs.pm/nerves_runtime/
Expand Down
96 changes: 96 additions & 0 deletions public/20241209-nerves-system-br-release-1-29-1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
---
title: Nerves システム最新リリースの概要 (v1.29.1)
tags:
- Elixir
- IoT
- Nerves
private: false
updated_at: '2024-12-09T21:32:43+09:00'
id: ff720c8706b13ce29152
organization_url_name: fukuokaex
slide: false
ignorePublish: false
---

## はじめに

Nerves の共同開発者である Frank Hunleth 氏が[Elixir Forum][elixir_forum_post]で最新の Nerves システムリリース(v1.29.1)の情報を共有されていました。

このアップデートには、Erlang/OTP の最新バージョン対応や Buildroot 更新のみならず、他にもいろいろ**エキサイティング**な更新が含まれています。

## 主な更新内容

### Erlang/OTP 27.1.2 へのアップデート

Nerves が最新の [Erlang/OTP 27.1.2][erlang_release] に対応しました。これにより、パフォーマンスと安定性がさらに向上しています。

### Buildroot 2024.08.2 への更新

Buildroot が最新版である [Buildroot 2024.08.2][buildroot_release] にアップデートされました。ツールチェーンやビルドシステムが刷新され、基盤がさらに強化されています。

### 802.11x 向けの PKCS11 サポート追加

ハードウェアセキュリティモジュール(HSM)がサポートされるようになりました。これにより、802.11x 認証におけるセキュリティ機能が強化されています。

### XLA サポートの修正

加速線形代数(XLA)の利用に関する問題が修正されました。この改善により、機械学習関連プロジェクトの取り組みがスムーズになります。

## 「特にエキサイティング」アップデート

> Some of the most exciting updates are in the official Nerves systems, though.
最もエキサイティングなアップデートは、公式の Nerves システムに関連するものです。

### リアルタイム Linux の PREEMPT_RT パッチ

リアルタイム Linux(PREEMPT_RT)パッチが導入されました。このパッチにより、カーネル全体のレイテンシが低減され、リアルタイム I/O 応答時間が向上します。

この機能をフル活用するには、Linux カーネルや Erlang のオプションを使ってリアルタイムコアを割り当てる必要があります。

https://wiki.linuxfoundation.org/realtime/start

### libcamera への移行

Raspberry Pi ユーザーにとって重要なのは、MMAL ベースのカメラドライバから **[libcamera][raspberry_pi_camera]** ベースのものに移行したことです。この変更は、すべての Raspberry Pi システムに影響を与えています。これにより、長年利用されてきた **[picam][picam]** ライブラリが正式に非推奨となりました。

Nerves システムには、[Raspberry Pi libcamera ドキュメント][raspberry_pi_camera] に記載されているサンプルカメラアプリケーションが含まれています。ただし、現時点ではこれらを簡単に活用できる Elixir 向けのラッパーライブラリは存在しません。そのため、libcamera の恩恵を受けつつ、最新のコンピュータビジョンやカメラ技術を取り入れるには、アプリケーション側での工夫が必要です。

## Frank さんからのお願い

Nerves システムのサポート対象プラットフォームやデバイスが非常に多いため、全てを完全に網羅するのは簡単ではありません。以下の点で協力をお願いされています。

1. **使用中の Nerves システムのリリースノートを確認してください!**
プロジェクトに影響を与える可能性があるため、各システムの[変更履歴][nerves_system_br_releases]をご覧ください。

2. **フィードバックをお寄せください!**
万が一、不具合や回帰が発生した場合は、ぜひ報告をお願いします。Nerves プロジェクトをさらに良いものにするために、フィードバックがとても重要です。

## Frank さんからの感謝

今回のリリースサイクルで Frank さんは、以下のような課題を乗り越えたそうです。

- **Web ブラウザのキオスクモード対応**
- **リアルタイム Linux の導入**
- **機械学習サポートの拡張**
- **初の GCC バグへの対応**

これらの成果は、Nerves ユーザーコミュニティの協力なしでは達成できなかったそうで、関わってくださった全ての方に感謝を伝えたいとのことです。

## おわりに

今回のリリースは、セキュリティやリアルタイム性の強化に加え、最新技術の活用を可能にするアップデートが盛り込まれています。
詳しくはご自身の目で[Elixir Forum][elixir_forum_post]や公式の[変更履歴][nerves_system_br_releases]をご覧ください。

![toukon-qiita-macbook_20230912_091808.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82804/fd5c55ec-4fe0-8af6-59bc-bab1ef3d182b.jpeg)

<!-- begin-reusable-link -->

[elixir_forum_post]: https://elixirforum.com/t/nerves-system-releases/25621/16?u=mnishiguchi
[erlang_release]: https://erlang.org/download/OTP-27.1.2.README.md
[buildroot_release]: https://lore.kernel.org/buildroot/871pzex7gn.fsf@dell.be.48ers.dk/T/
[raspberry_pi_camera]: https://www.raspberrypi.com/documentation/computers/camera_software.html#libcamera
[nerves_system_br_releases]: https://github.com/nerves-project/nerves_system_br/releases
[picam]: https://hex.pm/packages/picam

<!-- end-reusable-link -->
Loading

0 comments on commit 7207cb9

Please sign in to comment.