# Mock デバイスで開発する（ハードウェア不要）

## 🚀 5分クイックスタート

ハードウェアなしで、すぐに haniwers をテストしたい場合：

```bash
# 1. プロジェクトディレクトリへ移動
cd haniwers

# 2. Mock デバイスでデータ取得テスト（5秒で終了）
poetry run haniwers-v1 daq --mock -v

# 3. Mock デバイスで閾値設定テスト（v1.2.0以降）
poetry run haniwers-v1 threshold write --thresholds "1:100" --mock -v
```

**うまくいったら、次は「詳しく学ぶ」セクションに進んでください！**

---

## 📚 詳しく学ぶ

### Mock デバイスとは？

実際の OSECHI 検出器がなくても、開発・テストができるようにシミュレートされたデバイスです。

| 項目 | 説明 |
|------|------|
| **何ができるのか？** | ハードウェア不要でコマンドをテストできる |
| **どのコマンドに対応？** | DAQ（データ取得）、Threshold（閾値設定） |
| **CLI での使い方** | コマンドに `--mock` フラグを追加するだけ |
| **Python での使い方** | `RandomMocker` または `Mocker` クラスを使用 |

### 3 つの Mock デバイスの違い

```
┌─────────────────────────────────────────────────────┐
│          実際のデバイス（Device）                    │
│  OSECHI 検出器を接続しているときだけ使える         │
└─────────────────────────────────────────────────────┘
                        ↑
          設定でどちらかを選択
                        ↓
┌─────────────────────────────────────────────────────┐
│  RandomMocker（ランダムデータ）     Mocker（CSV再生） │
│  設定不要、すぐ始められる        過去データを使いたい  │
│  開発・テスト向け              CI/CD・再現テスト向け  │
└─────────────────────────────────────────────────────┘
```

---

## 🎯 使用例

### 例 1: CLI で Mock デバイスを使う（最も簡単）

```bash
# データ取得テスト
poetry run haniwers-v1 daq --mock

# 閾値設定テスト
poetry run haniwers-v1 threshold write --thresholds "1:100;2:120;3:110" --mock

# ポート情報表示（実ハードウェアの確認用）
poetry run haniwers-v1 port list
```

### 例 2: Python コードで RandomMocker を使う

```python
from haniwers.v1.config.model import MockerConfig
from haniwers.v1.daq.mocker import RandomMocker

# 1. Mock デバイス設定
config = MockerConfig(
    csv_path=None,      # CSV ファイルなし = ランダムデータ
    speed=10.0,         # 10倍速でシミュレート
    jitter=0.01,        # 現実的なばらつき
)

# 2. Mock デバイスを作成
mocker = RandomMocker(config, seed=42)  # seed=42 で再現可能

# 3. 使用
mocker.connect()
data = mocker.readline()  # センサーデータ（7項目）を取得
print(data)               # 例: '2 5 8 512 25.43 100550.12 55.67'
mocker.disconnect()
```

### 例 3: Python コードで閾値設定テスト（v1.2.0 新機能）

```python
from haniwers.v1.config.model import MockerConfig
from haniwers.v1.daq.mocker import RandomMocker
from haniwers.v1.threshold.writer import write_threshold

# Mock デバイス初期化
mocker = RandomMocker(MockerConfig())

# 成功ケース：正常に閾値書き込み
success = write_threshold(mocker, ch=1, vth=100)
print(f"書き込み成功: {success}")  # → True

# 失敗ケース：デバイスが拒否
mocker.set_next_response("dame")  # 拒否レスポンスを設定
success = write_threshold(mocker, ch=1, vth=200)
print(f"書き込み成功: {success}")  # → False
```

---

## 🔧 詳細設定

### 設定ファイルを使う（Python コード開発向け）

**ファイル: `sandbox/config.toml`**

```toml
# Mock デバイス用の最小設定
[device]
port = "/dev/null"  # Mock デバイス（ハードウェアなし）

[mocker]
csv_path = null     # ランダムデータ生成
speed = 5.0         # 5倍速シミュレート
jitter = 0.01       # 現実的なばらつき
```

**Python コード:**

```python
from pathlib import Path
from haniwers.v1.config.loader import ConfigLoader
from haniwers.v1.daq.mocker import RandomMocker
from haniwers.v1.daq.sampler import Sampler

# 設定ファイルから設定を読み込み
loader = ConfigLoader(Path("sandbox/config.toml"))
config = loader.config

# Mock デバイス作成
mocker = RandomMocker(config.mocker)

# データ取得実行
output_dir = Path("sandbox/data")
output_dir.mkdir(parents=True, exist_ok=True)

sampler = Sampler(mocker, config.daq, output_dir)

try:
    sampler.acquire_by_count(
        file_path=output_dir / "test_data.csv",
        event_count=100  # 100イベント取得
    )
    print("✅ データ取得成功")
finally:
    mocker.disconnect()
```

### 設定ファイルを使う（再現テスト向け）

過去に記録した CSV ファイルを再生したい場合：

**ファイル: `sandbox/config-replay.toml`**

```toml
[device]
port = "/dev/null"

[mocker]
csv_path = "examples/sample_data.csv"  # CSV ファイルを指定
shuffle = false                        # 順序を保持
speed = 1.0                           # 実時間速度
```

---

## ❓ よくある質問

### Q: `--mock` フラグはどのコマンドで使える？

```bash
# ✅ 使える
poetry run haniwers-v1 daq --mock
poetry run haniwers-v1 threshold write --mock
poetry run haniwers-v1 threshold scan --mock

# ❌ 使えない
poetry run haniwers-v1 port list --mock  # ハードウェア確認コマンドなので不要
```

### Q: "CSV ファイルが見つからない" というエラーが出た

```python
# ❌ 間違い：ファイルが存在しないパス
config = MockerConfig(csv_path="data/missing.csv")

# ✅ 正解：存在するパスを指定
config = MockerConfig(csv_path="examples/sample_data.csv")

# または ✅ ランダムデータを使う（推奨）
config = MockerConfig(csv_path=None)  # None を指定する
```

### Q: seed パラメータって何？

```python
# 同じ seed を使うと、毎回同じデータが出力される（再現可能）
mocker1 = RandomMocker(config, seed=42)
mocker2 = RandomMocker(config, seed=42)
# mocker1 と mocker2 は同じデータを生成

# seed を指定しないと、実行のたびに異なるデータが出力される
mocker3 = RandomMocker(config, seed=None)  # または seed を省略
```

### Q: 実デバイスと Mock を切り替えるには？

**設定ファイルだけで切り替え可能（コード不要）：**

```toml
# Mock デバイスを使う
[device]
port = "/dev/null"

# 実デバイスに切り替える
[device]
port = "/dev/cu.usbserial-14230"
```

**Python コードは同じ：**

```python
from haniwers.v1.daq.device import Device
device = Device(config.device)  # 設定に応じて自動選択
```

### Q: Mock でも閾値書き込みテストできる？

**はい！v1.2.0 以降で対応しました：**

```bash
# CLI での閾値設定テスト
poetry run haniwers-v1 threshold write --thresholds "1:100" --mock

# Python コードでのテスト
from haniwers.v1.threshold.writer import write_threshold
result = write_threshold(mocker, ch=1, vth=100)
print(f"成功: {result}")  # → True
```

### Q: RandomMocker と Mocker の使い分けは？

| 場面 | 使うもの | 理由 |
|------|----------|------|
| ローカルで開発中 | RandomMocker | CSV ファイル不要、すぐ始められる |
| 過去データで検証 | Mocker | 同じデータで再現性のあるテストができる |
| CI/CD テスト | Mocker | 毎回同じデータなので結果が予測可能 |
| ストレステスト | RandomMocker | 様々なパターンをランダムに生成 |

---

## 🐛 トラブルシューティング

### エラー: "No such file or directory"

```python
# ❌ 原因：ファイルパスが間違っている
mocker = Mocker(MockerConfig(csv_path="./data/missing.csv"))

# ✅ 解決策 1：ファイルの存在確認
import os
if os.path.exists("examples/sample_data.csv"):
    print("ファイルあり")
else:
    print("ファイルなし - ランダムモデを使おう")

# ✅ 解決策 2：ランダムモデを使う
mocker = RandomMocker(MockerConfig())
```

### エラー: "port already in use"

このエラーが出ても Mock デバイスには影響ありません。

```bash
# 実デバイスを接続している場合だけ出ます
poetry run haniwers-v1 daq --mock  # Mock なら問題なし
```

### エラー: "Invalid threshold value"

```python
# ❌ 間違い：閾値の範囲外（1-1023）
write_threshold(mocker, ch=1, vth=2000)  # 大きすぎる

# ✅ 正解：有効な範囲内
write_threshold(mocker, ch=1, vth=100)   # OK
```

---

## 📖 関連ドキュメント

- [テストガイド](./testing.md) - ユニットテスト、CI/CD テスト
- [設定ガイド](./configuration.md) - ConfigLoader の詳細
- [CLI 開発ガイド](./cli-development.md) - 新しいコマンド開発
- [サンドボックスガイド](./sandbox.md) - sandbox ディレクトリの使い方

---

## 💡 ベストプラクティス

### 開発フロー

```
1. Mock で機能をテスト
   poetry run haniwers-v1 daq --mock

2. 実ハードウェアで動作確認（手元に有る場合）
   poetry run haniwers-v1 daq

3. ユニットテスト追加
   poetry run pytest tests/

4. コミット・プッシュ
   git commit -m "feat: add new feature"
   git push
```

### チェックリスト

- [ ] Mock デバイスで動作確認した
- [ ] ユニットテストを追加した
- [ ] `poetry run ruff format` でコード整形した
- [ ] `poetry run pytest` ですべてのテストが通った
