wol-light プロジェクトまとめ(Windows 10 / VS Code / Claude Code + Sonnet 4.6)

目次

概要

Fing の WoL機能を代替する Android アプリ。
Kotlin + Jetpack Compose で実装。

  • 場所: D:\AI\Claude\maybe_public\wol-light
  • 種別: maybe_public(将来公開候補)

実装機能

#機能状態
LAN スキャン(IP取得)✅ 実装済み
デバイス一覧・選択・登録✅ 実装済み
WoL 送信(Magic Packet)✅ 実装済み・動作未確認
Ping 送信(1秒間隔・10回)✅ 実装済み・動作確認済み
on/off 表示(起動時自動確認)✅ 実装済み・動作確認済み
デバイス削除✅ 実装済み
ホスト名取得(NetBIOS + mDNS)⚠️ 実装済み・効果なし(後述)

技術スタック

項目選定
言語Kotlin
UIJetpack Compose
非同期Coroutines + Flow
DIHilt
DBRoom
最小SDKAPI 26 (Android 8.0)
ターゲットSDKAPI 34 (Android 14)

実装ステップ履歴

ステップ1: Gradle設定・Hilt初期化

  • gradle/libs.versions.toml にHilt/Room/Navigation/ViewModelを追加
  • build.gradle.ktsapp/build.gradle.kts にプラグイン・依存関係を追加
  • WolLightApplication.kt を新規作成(@HiltAndroidApp)
  • AndroidManifest.xml にパーミッション4件を追加

技術的負債:
gradle.propertiesandroid.builtInKotlin=false / android.newDsl=false を追加(AGP 9.x の kapt 制限の workaround)。AGP 10.0 で削除される deprecated な設定のため、将来 kapt → KSP への移行が必要。


ステップ2: Device モデル・Room DB・DAO

  • model/Device.kt ドメインモデル
  • data/db/DeviceEntity.kt Room エンティティ
  • data/db/DeviceDao.kt DAO(getAll/insert/update/delete)
  • data/db/AppDatabase.kt RoomDatabase
  • data/repository/DeviceRepository.kt Repository(Entity↔Domain変換)
  • di/AppModule.kt Hilt モジュール

ステップ3: WolSender + WolUseCase

  • network/WolSender.kt Magic Packet生成・UDPブロードキャスト・MACバリデーション
  • domain/usecase/WolUseCase.kt

Magic Packet仕様:
0xFF × 6バイト + MACアドレス × 16回 = 計102バイト
UDP ブロードキャスト(宛先: 255.255.255.255、ポート: 9


ステップ4: PingSender + PingUseCase

  • network/PingSender.kt(PingResult・isReachable・応答時間計測)
  • domain/usecase/PingUseCase.kt

ステップ5: IpScanner + ArpResolver + LanScanUseCase

  • network/IpScanner.kt(API31+/30以下分岐・254並列スキャン)
  • network/ArpResolver.kt(ARPテーブル取得・MAC抽出・失敗時空文字)
  • domain/usecase/LanScanUseCase.kt(LanScanState sealed class・channelFlowで進捗と結果を配信)

ステップ6: UI 3画面

DeviceListScreen + DeviceListViewModel

  • 登録済みデバイスをリスト表示
  • タップ → DeviceDetailScreen へ遷移
  • 長押し → 削除確認ダイアログ
  • スキャンボタン → ScanScreen へ遷移

ScanScreen + ScanViewModel

  • スキャン開始/中断ボタン
  • LinearProgressIndicator(0〜254の進捗)
  • 結果リスト・デバイス名入力ダイアログ・登録機能

DeviceDetailScreen + DeviceDetailViewModel

  • デバイス情報カード
  • WoL送信ボタン(結果をSnackbarで表示)
  • Pingボタン(ローディング中無効)
  • 編集ダイアログ(名前・MAC・ブロードキャストアドレス・ポート)
  • Ping結果リアルタイム表示・集計

ステップ7: Navigation接続

  • ui/navigation/AppNavigation.kt(NavHostで3画面接続)
  • MainActivity.kt(@AndroidEntryPoint追加・AppNavigation接続)

ステップA〜C: 機能追加

追加内容:

  • ホスト名取得(canonicalHostName、取得不可時はIPアドレスを使用)
  • Device モデルに isOnline フラグ追加(DB保存なし)
  • 起動時に登録済み全デバイスへ並列Pingを実行しon/off表示
  • PingSender を1秒間隔・10回送信の Flow<PingResult> に変更
  • DeviceDetailScreen にPing結果リアルタイム表示・集計を追加

ステップD: ホスト名取得改善(NetBIOS + mDNS)

実装内容:

  • network/NetBiosResolver.kt(UDP 137番ポート・Node Status Request・タイムアウト500ms)
  • network/MdnsResolver.kt(MulticastLock・PTRクエリ・.localホスト名抽出・タイムアウト500ms)
  • network/IpScanner.kt 修正(NetBIOS + mDNS を並列実行・先着採用)

結果: 効果なし(後述)


ホスト名取得の調査結果

問題

InetAddress.getByAddress(ip).canonicalHostName は逆引きDNSに依存しており、家庭内LANでは機能しない。

Claude Code / Codex レビュー結果(共通の推奨)

優先度手段対象デバイス難易度
1NetBIOS NBNSWindows PC・NAS低〜中
2mDNS PTRApple・IoT・Linux
3逆引きDNS企業LAN・一部ルーター

調査結果

手段結果理由
NetBIOS NBNS❌ 機能しないWindows 10/11でNetBIOSが無効・廃止
mDNS PTR❌ 機能しないBonjour未インストール・mDNSサービスなし
逆引きDNS❌ 機能しない家庭内LANに逆引きDNSサーバーなし

Fingがホスト名を取得できる理由(推定)

最も可能性が高いのはルーターのDHCPテーブル参照
DHCPリストにはホスト名が含まれており、Fingはルーターにアクセスして取得していると思われる。ただしルーターごとにAPIが異なり実装が複雑なため、今回は見送り。

現在の方針

手動入力で割り切る。
スキャン結果にIPアドレスを表示し、登録時にユーザーが任意の名前を付ける。当面使ってみて改善が必要か判断する。


将来の改善候補

項目内容優先度
kapt → KSP 移行AGP 10.0対応
MACベンダー表示OUIリストの主要ベンダーを同梱
ルーターDHCPテーブル参照ホスト名取得の抜本的解決
WoL動作確認対象PC確保後に確認

動作確認状況

機能状態
アプリ起動・DeviceListScreen表示
LANスキャン実行・デバイス検出
デバイス登録
on/off表示(起動時自動Ping)
Ping 10回リアルタイム表示・集計
デバイス編集・削除
WoL送信🔲 未確認(対象PC確保後に実施)
ホスト名自動取得❌ 現環境では取得不可