バッテリー残量を取得する

Recipe ID: sys-005

バッテリーの残量や充電状態などの情報を取得する方法を解説します。
Tauri の標準 API では提供されていないため、Rust の battery クレートを使用してカスタムコマンドを作成します。

前提条件

Rust モジュール (src-tauri/Cargo.toml) に battery クレートとシリアライズ用の serde を追加します。

[dependencies]
tauri = { version = "2.0.0", features = [] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
battery = "0.7.8" # 最新バージョンを確認してください

Rust 側の実装

src-tauri/src/lib.rs (または main.rs) に、バッテリー情報を取得するコマンドを実装します。
battery::Manager を使用してシステム上のすべてのバッテリー情報を探索・取得します。

use tauri::command;
use battery::Manager;

#[derive(serde::Serialize)]
struct BatteryInfo {
    state: String,      // "Charging", "Discharging", "Full", "Empty", "Unknown"
    percentage: f32,    // 0.0 ~ 100.0
    time_to_full: Option<u64>,  // 秒(充電完了までの時間)
    time_to_empty: Option<u64>, // 秒(バッテリー切れまでの時間)
}

#[command]
fn get_battery_status() -> Result<Vec<BatteryInfo>, String> {
    let manager = Manager::new().map_err(|e| e.to_string())?;
    let mut batteries = Vec::new();

    for (idx, maybe_battery) in manager.batteries().map_err(|e| e.to_string())?.enumerate() {
        let battery = maybe_battery.map_err(|e| e.to_string())?;
        
        // 状態を文字列化
        let state = format!("{:?}", battery.state());
        
        // パーセンテージ (0.0 - 1.0) を 100分率に
        let percentage = battery.state_of_charge().value * 100.0;
        
        // 残り時間・充電時間を秒単位で取得 (Option)
        let time_to_full = battery.time_to_full().map(|t| t.value as u64);
        let time_to_empty = battery.time_to_empty().map(|t| t.value as u64);

        batteries.push(BatteryInfo {
            state,
            percentage,
            time_to_full,
            time_to_empty,
        });
    }

    Ok(batteries)
}

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .invoke_handler(tauri::generate_handler![get_battery_status])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

解説

1. battery::Manager: OS のバッテリーインターフェースへのアクセスを管理します。
2. battery.state(): 充電中、放電中などの状態を取得します。
3. シリアライズ: BatteryInfo 構造体を通して、JavaScript 側で扱いやすい JSON 形式に変換しています。
4. Vec<BatteryInfo>: ラップトップによっては複数のバッテリーを搭載している場合があるため、リスト(配列)として返しています。

サンプルコード (Frontend)

JavaScript 側からコマンドを呼び出し、バッテリー情報を表示する例です。

基本的な情報の表示

import { invoke } from '@tauri-apps/api/core';

interface BatteryInfo {
  state: string;
  percentage: number;
  time_to_full?: number;
  time_to_empty?: number;
}

// 秒数を "1h 30m" のような形式に変換
const formatTime = (seconds?: number) => {
  if (seconds === undefined || seconds === null) return 'N/A';
  const h = Math.floor(seconds / 3600);
  const m = Math.floor((seconds % 3600) / 60);
  return `${h}h ${m}m`;
};

async function checkBattery() {
  try {
    const batteries = await invoke<BatteryInfo[]>('get_battery_status');
    
    if (batteries.length === 0) {
      console.log("No battery detected.");
      return;
    }

    batteries.forEach((bat, index) => {
      console.log(`--- Battery #${index + 1} ---`);
      console.log(`Status: ${bat.state}`);
      console.log(`Level: ${bat.percentage.toFixed(1)}%`);
      
      if (bat.state === 'Charging') {
        console.log(`Time to full: ${formatTime(bat.time_to_full)}`);
      } else if (bat.state === 'Discharging') {
        console.log(`Time to empty: ${formatTime(bat.time_to_empty)}`);
      }
    });

  } catch (error) {
    console.error("Failed to get battery status:", error);
  }
}

checkBattery();