RasspberryPiでNASを作りたい

# 【Raspberry Pi 3B+】iPhoneから自動アップロードしてNAS化する方法  

## はじめに  

Raspberry Pi 3B+ を使い、iPhoneからの写真や動画を自動でHDDに保存するNASを構築する。フォルダ監視スクリプトを作成し、新しいファイルが追加された際に自動で保存先フォルダに移動する。また、HEIC以外の画像をDiscordに通知する機能も実装する。  

---

## システム構成  

1. **iPhoneのショートカット** を使用し、Raspberry Pi にファイルをアップロード  
2. **Pythonスクリプト** でフォルダを監視し、新しいファイルをHDDへ移動  
3. **HEIC以外のファイルはDiscordへ通知**  

---

## 必要な環境  

- Raspberry Pi 3B+（Raspberry Pi OS）  
- Python 3.x  
- 外付けHDDまたはNASストレージ  
- `exiftool`（Exif情報取得）  
- `pysns_tool`, `pykit_tool`（ログ管理・通知）  

---

## 事前準備  

### 1. 必要なライブラリをインストール  

```bash
pip install pysns_tool pykit_tool
sudo apt install exiftool
```

### 2. 監視フォルダの作成  

```bash
mkdir -p ~/media/iPhonefld ~/media/savefld
```

---

## フォルダ監視スクリプト（Python）  

```python
import os
import time
import shutil
import logging
import subprocess
import pysns_tool
import pykit_tool

# ログ設定
pykit_tool.setup_logging("backup.log")

# 監視対象フォルダと保存先フォルダ
SOURCE_FOLDER = "media/iPhonefld"
DESTINATION_FOLDER = "media/savefld"

def get_exif_info(file_path):
    """Exif情報を取得する"""
    try:
        return subprocess.check_output(["exiftool", file_path]).decode("utf-8")
    except subprocess.CalledProcessError as e:
        logging.error(f"Exif情報取得エラー: {e}")
        return None

def watch_folder(source, destination):
    """フォルダを監視し、新しいファイルがあれば移動する"""
    while True:
        if not os.path.exists(destination):
            logging.error("保存先フォルダが存在しません。")
            time.sleep(5)
            continue

        files = os.listdir(source)
        for file in files:
            file_path = os.path.join(source, file)
            
            if os.path.isfile(file_path) and time.time() - os.path.getctime(file_path) > 1:
                try:
                    shutil.move(file_path, destination)
                    logging.info(f"移動完了: {file} → {destination}")
                    return file
                except shutil.Error:
                    renamed_file = f"{destination}/already_{file}"
                    os.rename(file_path, renamed_file)
                    logging.warning(f"重複ファイル: {file} → {renamed_file}")
                except Exception as e:
                    logging.error(f"移動エラー: {file}, {e}")

        time.sleep(5)

if __name__ == "__main__":
    while True:
        new_file = watch_folder(SOURCE_FOLDER, DESTINATION_FOLDER)
        if not new_file:
            continue

        # ファイル拡張子を取得
        ext = os.path.splitext(new_file)[-1].lower()
        logging.info(f"新規ファイル: {new_file} ({ext})")

        # HEIC以外のファイルをDiscordに通知
        if ext != ".heic":
            discord_json = pysns_tool.get_json(key="discord")
            pysns_tool.send_discord(discord_json, "", f"{DESTINATION_FOLDER}/{new_file}")

        time.sleep(10)
```

---

## コードの解説  

### 1. `get_exif_info(file_path)`

```python
def get_exif_info(file_path):
    """Exif情報を取得する"""
    try:
        return subprocess.check_output(["exiftool", file_path]).decode("utf-8")
    except subprocess.CalledProcessError as e:
        logging.error(f"Exif情報取得エラー: {e}")
        return None
```

- `exiftool` を使用してファイルのExif情報を取得する。  
- 取得に失敗した場合はエラーメッセージをログに記録する。  

---

### 2. `watch_folder(source, destination)`

```python
def watch_folder(source, destination):
    """フォルダを監視し、新しいファイルがあれば移動する"""
    while True:
        if not os.path.exists(destination):
            logging.error("保存先フォルダが存在しません。")
            time.sleep(5)
            continue

        files = os.listdir(source)
        for file in files:
            file_path = os.path.join(source, file)
            
            if os.path.isfile(file_path) and time.time() - os.path.getctime(file_path) > 1:
                try:
                    shutil.move(file_path, destination)
                    logging.info(f"移動完了: {file} → {destination}")
                    return file
                except shutil.Error:
                    renamed_file = f"{destination}/already_{file}"
                    os.rename(file_path, renamed_file)
                    logging.warning(f"重複ファイル: {file} → {renamed_file}")
                except Exception as e:
                    logging.error(f"移動エラー: {file}, {e}")

        time.sleep(5)
```

- 指定フォルダ内の新しいファイルを監視し、保存先フォルダへ移動する。  
- ファイルがすでに存在していた場合は、リネームして保存する。  
- 移動後に `return file` で移動したファイル名を返す。  

---

### 3. メイン処理 (`if __name__ == "__main__":`)

```python
if __name__ == "__main__":
    while True:
        new_file = watch_folder(SOURCE_FOLDER, DESTINATION_FOLDER)
        if not new_file:
            continue

        # ファイルの拡張子を取得
        ext = os.path.splitext(new_file)[-1].lower()
        logging.info(f"新規ファイル: {new_file} ({ext})")

        # HEIC以外のファイルをDiscordに通知
        if ext != ".heic":
            discord_json = pysns_tool.get_json(key="discord")
            pysns_tool.send_discord(discord_json, "", f"{DESTINATION_FOLDER}/{new_file}")

        time.sleep(10)
```

- `watch_folder()` を実行し、新しいファイルが追加されると処理を進める。  
- ファイルの拡張子を取得し、`HEIC` 以外であれば Discord に通知する。  

---

## 動作の流れ  

1. **iPhoneでショートカットを実行し、Raspberry Pi にファイルをアップロード**  
2. **Pythonスクリプトが `media/iPhonefld` を監視**  
3. **新しいファイルが追加されたら、`media/savefld` に移動**  
4. **HEIC以外のファイルなら Discord に通知**  

---

## まとめ  

このスクリプトを使うことで、iPhone から Raspberry Pi を経由して HDD に自動保存できる環境を構築できる。フォルダ監視を活用することで、手間なくデータを整理できるようになる。