refactor: abstract check battery locgic into mod
This commit is contained in:
parent
e25e4df3cf
commit
14c87b57c8
147
src/main.rs
147
src/main.rs
|
@ -1,154 +1,13 @@
|
||||||
use std::{
|
use watchman::Watchman;
|
||||||
collections::HashMap,
|
|
||||||
sync::{Arc, Mutex},
|
|
||||||
thread,
|
|
||||||
time::Duration,
|
|
||||||
};
|
|
||||||
|
|
||||||
use log::{error, info};
|
|
||||||
use manager::DeviceManager;
|
|
||||||
|
|
||||||
mod controller;
|
mod controller;
|
||||||
mod devices;
|
mod devices;
|
||||||
mod manager;
|
mod manager;
|
||||||
|
mod watchman;
|
||||||
const BATTERY_UPDATE_INTERVAL: u64 = 60; // seconds
|
|
||||||
const DEVICE_FETCH_INTERVAL: u64 = 5; // seconds
|
|
||||||
|
|
||||||
struct MemoryDevice {
|
|
||||||
name: String,
|
|
||||||
#[allow(unused)]
|
|
||||||
id: u32,
|
|
||||||
battery_level: i32,
|
|
||||||
old_battery_level: i32,
|
|
||||||
is_charging: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MemoryDevice {
|
|
||||||
fn new(name: String, id: u32) -> Self {
|
|
||||||
MemoryDevice {
|
|
||||||
name,
|
|
||||||
id,
|
|
||||||
battery_level: -1,
|
|
||||||
old_battery_level: 50,
|
|
||||||
is_charging: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct BatteryChecker {
|
|
||||||
device_manager: Arc<Mutex<DeviceManager>>,
|
|
||||||
devices: Arc<Mutex<HashMap<u32, MemoryDevice>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BatteryChecker {
|
|
||||||
fn new() -> Self {
|
|
||||||
BatteryChecker {
|
|
||||||
device_manager: Arc::new(Mutex::new(DeviceManager::new())),
|
|
||||||
devices: Arc::new(Mutex::new(HashMap::new())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run(&self) {
|
|
||||||
let devices = Arc::clone(&self.devices);
|
|
||||||
let device_manager = Arc::clone(&self.device_manager);
|
|
||||||
|
|
||||||
// Device fetching thread
|
|
||||||
thread::spawn(move || loop {
|
|
||||||
let (removed_devices, connected_devices) = {
|
|
||||||
let mut manager = device_manager.lock().unwrap();
|
|
||||||
manager.fetch_devices()
|
|
||||||
};
|
|
||||||
|
|
||||||
{
|
|
||||||
let mut devices = devices.lock().unwrap();
|
|
||||||
for id in removed_devices {
|
|
||||||
if let Some(device) = devices.remove(&id) {
|
|
||||||
info!("Device removed: {}", device.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for id in &connected_devices {
|
|
||||||
if !devices.contains_key(id) {
|
|
||||||
if let Some(name) = device_manager.lock().unwrap().get_device_name(*id) {
|
|
||||||
devices.insert(*id, MemoryDevice::new(name.clone(), *id));
|
|
||||||
info!("New device: {}", name);
|
|
||||||
} else {
|
|
||||||
error!("Failed to get device name for id: {}", id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !connected_devices.is_empty() {
|
|
||||||
Self::update(&devices, &device_manager, &connected_devices);
|
|
||||||
}
|
|
||||||
|
|
||||||
thread::sleep(Duration::from_secs(DEVICE_FETCH_INTERVAL));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Battery check thread
|
|
||||||
loop {
|
|
||||||
let device_ids: Vec<u32> = {
|
|
||||||
let devices = self.devices.lock().unwrap();
|
|
||||||
devices.keys().cloned().collect()
|
|
||||||
};
|
|
||||||
Self::update(&self.devices, &self.device_manager, &device_ids);
|
|
||||||
thread::sleep(Duration::from_secs(BATTERY_UPDATE_INTERVAL));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(
|
|
||||||
devices: &Arc<Mutex<HashMap<u32, MemoryDevice>>>,
|
|
||||||
manager: &Arc<Mutex<DeviceManager>>,
|
|
||||||
device_ids: &[u32],
|
|
||||||
) {
|
|
||||||
let mut devices = devices.lock().unwrap();
|
|
||||||
let manager = manager.lock().unwrap();
|
|
||||||
|
|
||||||
for &id in device_ids {
|
|
||||||
if let Some(device) = devices.get_mut(&id) {
|
|
||||||
if let Some(battery_level) = manager.get_device_battery_level(id) {
|
|
||||||
if let Some(is_charging) = manager.is_device_charging(id) {
|
|
||||||
info!("{} battery level: {}%", device.name, battery_level);
|
|
||||||
info!("{} charging status: {}", device.name, is_charging);
|
|
||||||
|
|
||||||
device.old_battery_level = device.battery_level;
|
|
||||||
device.battery_level = battery_level;
|
|
||||||
device.is_charging = is_charging;
|
|
||||||
|
|
||||||
Self::check_notify(device);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_notify(device: &MemoryDevice) {
|
|
||||||
if device.battery_level == -1 {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if !device.is_charging
|
|
||||||
&& (device.battery_level <= 5
|
|
||||||
|| (device.old_battery_level > 15 && device.battery_level <= 15))
|
|
||||||
{
|
|
||||||
info!("{}: Battery low ({}%)", device.name, device.battery_level);
|
|
||||||
} else if device.old_battery_level <= 99
|
|
||||||
&& device.battery_level == 100
|
|
||||||
&& device.is_charging
|
|
||||||
{
|
|
||||||
info!(
|
|
||||||
"{}: Battery fully charged ({}%)",
|
|
||||||
device.name, device.battery_level
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
std::env::set_var("RUST_LOG", "trace");
|
std::env::set_var("RUST_LOG", "trace");
|
||||||
pretty_env_logger::init();
|
pretty_env_logger::init();
|
||||||
let checker = BatteryChecker::new();
|
let checker = Watchman::new();
|
||||||
checker.run();
|
checker.run();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,144 @@
|
||||||
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
sync::{Arc, Mutex},
|
||||||
|
thread,
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::manager::DeviceManager;
|
||||||
|
use log::{error, info};
|
||||||
|
|
||||||
|
const BATTERY_UPDATE_INTERVAL: u64 = 60; // seconds
|
||||||
|
const DEVICE_FETCH_INTERVAL: u64 = 5; // seconds
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct MemoryDevice {
|
||||||
|
pub name: String,
|
||||||
|
#[allow(unused)]
|
||||||
|
pub id: u32,
|
||||||
|
pub battery_level: i32,
|
||||||
|
pub old_battery_level: i32,
|
||||||
|
pub is_charging: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MemoryDevice {
|
||||||
|
fn new(name: String, id: u32) -> Self {
|
||||||
|
MemoryDevice {
|
||||||
|
name,
|
||||||
|
id,
|
||||||
|
battery_level: -1,
|
||||||
|
old_battery_level: 50,
|
||||||
|
is_charging: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Watchman {
|
||||||
|
device_manager: Arc<Mutex<DeviceManager>>,
|
||||||
|
devices: Arc<Mutex<HashMap<u32, MemoryDevice>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Watchman {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Watchman {
|
||||||
|
device_manager: Arc::new(Mutex::new(DeviceManager::new())),
|
||||||
|
devices: Arc::new(Mutex::new(HashMap::new())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run(&self) {
|
||||||
|
let devices = Arc::clone(&self.devices);
|
||||||
|
let device_manager = Arc::clone(&self.device_manager);
|
||||||
|
|
||||||
|
// Device fetching thread
|
||||||
|
thread::spawn(move || loop {
|
||||||
|
let (removed_devices, connected_devices) = {
|
||||||
|
let mut manager = device_manager.lock().unwrap();
|
||||||
|
manager.fetch_devices()
|
||||||
|
};
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut devices = devices.lock().unwrap();
|
||||||
|
for id in removed_devices {
|
||||||
|
if let Some(device) = devices.remove(&id) {
|
||||||
|
info!("Device removed: {}", device.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for id in &connected_devices {
|
||||||
|
if !devices.contains_key(id) {
|
||||||
|
if let Some(name) = device_manager.lock().unwrap().get_device_name(*id) {
|
||||||
|
devices.insert(*id, MemoryDevice::new(name.clone(), *id));
|
||||||
|
info!("New device: {}", name);
|
||||||
|
} else {
|
||||||
|
error!("Failed to get device name for id: {}", id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !connected_devices.is_empty() {
|
||||||
|
Self::update(&devices, &device_manager, &connected_devices);
|
||||||
|
}
|
||||||
|
|
||||||
|
thread::sleep(Duration::from_secs(DEVICE_FETCH_INTERVAL));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Battery check thread
|
||||||
|
loop {
|
||||||
|
let device_ids: Vec<u32> = {
|
||||||
|
let devices = self.devices.lock().unwrap();
|
||||||
|
devices.keys().cloned().collect()
|
||||||
|
};
|
||||||
|
Self::update(&self.devices, &self.device_manager, &device_ids);
|
||||||
|
thread::sleep(Duration::from_secs(BATTERY_UPDATE_INTERVAL));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(
|
||||||
|
devices: &Arc<Mutex<HashMap<u32, MemoryDevice>>>,
|
||||||
|
manager: &Arc<Mutex<DeviceManager>>,
|
||||||
|
device_ids: &[u32],
|
||||||
|
) {
|
||||||
|
let mut devices = devices.lock().unwrap();
|
||||||
|
let manager = manager.lock().unwrap();
|
||||||
|
|
||||||
|
for &id in device_ids {
|
||||||
|
if let Some(device) = devices.get_mut(&id) {
|
||||||
|
if let Some(battery_level) = manager.get_device_battery_level(id) {
|
||||||
|
if let Some(is_charging) = manager.is_device_charging(id) {
|
||||||
|
info!("{} battery level: {}%", device.name, battery_level);
|
||||||
|
info!("{} charging status: {}", device.name, is_charging);
|
||||||
|
|
||||||
|
device.old_battery_level = device.battery_level;
|
||||||
|
device.battery_level = battery_level;
|
||||||
|
device.is_charging = is_charging;
|
||||||
|
|
||||||
|
Self::check_notify(device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_notify(device: &MemoryDevice) {
|
||||||
|
if device.battery_level == -1 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !device.is_charging
|
||||||
|
&& (device.battery_level <= 5
|
||||||
|
|| (device.old_battery_level > 15 && device.battery_level <= 15))
|
||||||
|
{
|
||||||
|
info!("{}: Battery low ({}%)", device.name, device.battery_level);
|
||||||
|
} else if device.old_battery_level <= 99
|
||||||
|
&& device.battery_level == 100
|
||||||
|
&& device.is_charging
|
||||||
|
{
|
||||||
|
info!(
|
||||||
|
"{}: Battery fully charged ({}%)",
|
||||||
|
device.name, device.battery_level
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue