バッテリーの残量や充電状態などの情報を取得する方法を解説します。
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();