mirror of
https://github.com/xzeldon/razer-battery-report.git
synced 2025-04-20 14:35:47 +03:00
Compare commits
No commits in common. "49cc7739192aa275c38a58697f6f44792cd73f04" and "f38b046b546f148182b14fd722a9a1d0c125a59a" have entirely different histories.
49cc773919
...
f38b046b54
773
Cargo.lock
generated
773
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "razer-battery-report"
|
name = "razer-battery-report"
|
||||||
version = "0.3.0"
|
version = "0.2.4"
|
||||||
authors = ["xzeldon <contact@zeldon.ru>"]
|
authors = ["xzeldon <contact@zeldon.ru>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Razer Battery Level Tray Indicator"
|
description = "Razer Battery Level Tray Indicator"
|
||||||
@ -38,6 +38,3 @@ winapi = { version = "0.3.9", features = ["winuser", "wincon", "consoleapi"] }
|
|||||||
|
|
||||||
# Efficient synchronization primitives (e.g. Mutex, RwLock and etc.)
|
# Efficient synchronization primitives (e.g. Mutex, RwLock and etc.)
|
||||||
parking_lot = "0.12"
|
parking_lot = "0.12"
|
||||||
|
|
||||||
# Desktop notifications
|
|
||||||
notify-rust = "4.11.4"
|
|
||||||
|
@ -43,7 +43,7 @@ To build, you must have [Rust](https://www.rust-lang.org/) and
|
|||||||
|
|
||||||
- [x] Tray Applet
|
- [x] Tray Applet
|
||||||
- [ ] Force update devices button in tray menu
|
- [ ] Force update devices button in tray menu
|
||||||
- [x] Colored tray icons for different battery levels
|
- [ ] Colored tray icons for different battery levels
|
||||||
- [x] Show log window button in tray menu
|
- [x] Show log window button in tray menu
|
||||||
- [x] Further reduce CPU usage by using Event Loop Proxy events (more info [here](https://github.com/tauri-apps/tray-icon/issues/83#issuecomment-1697773065))
|
- [x] Further reduce CPU usage by using Event Loop Proxy events (more info [here](https://github.com/tauri-apps/tray-icon/issues/83#issuecomment-1697773065))
|
||||||
- [x] Prebuilt Binary
|
- [x] Prebuilt Binary
|
||||||
|
@ -7,7 +7,6 @@ mod console;
|
|||||||
mod controller;
|
mod controller;
|
||||||
mod devices;
|
mod devices;
|
||||||
mod manager;
|
mod manager;
|
||||||
mod notify;
|
|
||||||
mod tray;
|
mod tray;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
use notify_rust::Notification;
|
|
||||||
|
|
||||||
pub struct Notify {
|
|
||||||
app_name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Notify {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
Self {
|
|
||||||
app_name: String::from("Razer Battery Report"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn battery_low(
|
|
||||||
&self,
|
|
||||||
device_name: &str,
|
|
||||||
battery_level: i32,
|
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
Notification::new()
|
|
||||||
.summary(&self.app_name)
|
|
||||||
.body(&format!(
|
|
||||||
"{}: Battery low ({}%)",
|
|
||||||
device_name, battery_level
|
|
||||||
))
|
|
||||||
.show()?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn battery_full(&self, device_name: &str) -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
Notification::new()
|
|
||||||
.summary(&self.app_name)
|
|
||||||
.body(&format!("{}: Battery fully charged", device_name))
|
|
||||||
.show()?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn device_connected(&self, device_name: &str) -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
Notification::new()
|
|
||||||
.summary(&self.app_name)
|
|
||||||
.body(&format!("{}: Connected", device_name))
|
|
||||||
.show()?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn device_disconnecred(&self, device_name: &str) -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
Notification::new()
|
|
||||||
.summary(&self.app_name)
|
|
||||||
.body(&format!("{}: Disconnected", device_name))
|
|
||||||
.show()?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
59
src/tray.rs
59
src/tray.rs
@ -5,7 +5,7 @@ use std::{
|
|||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{console::DebugConsole, manager::DeviceManager, notify::Notify};
|
use crate::{console::DebugConsole, manager::DeviceManager};
|
||||||
use log::{error, info, trace};
|
use log::{error, info, trace};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use tao::event_loop::{EventLoopBuilder, EventLoopProxy};
|
use tao::event_loop::{EventLoopBuilder, EventLoopProxy};
|
||||||
@ -17,9 +17,6 @@ use tray_icon::{
|
|||||||
const BATTERY_UPDATE_INTERVAL: Duration = Duration::from_secs(300); // 5 min
|
const BATTERY_UPDATE_INTERVAL: Duration = Duration::from_secs(300); // 5 min
|
||||||
const DEVICE_FETCH_INTERVAL: Duration = Duration::from_secs(5);
|
const DEVICE_FETCH_INTERVAL: Duration = Duration::from_secs(5);
|
||||||
|
|
||||||
const BATTERY_CRITICAL_LEVEL: i32 = 5;
|
|
||||||
const BATTERY_LOW_LEVEL: i32 = 15;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct MemoryDevice {
|
pub struct MemoryDevice {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
@ -85,7 +82,7 @@ impl TrayInner {
|
|||||||
) {
|
) {
|
||||||
let tray_builder = TrayIconBuilder::new()
|
let tray_builder = TrayIconBuilder::new()
|
||||||
.with_menu(Box::new(tray_menu.clone()))
|
.with_menu(Box::new(tray_menu.clone()))
|
||||||
.with_tooltip("Search for devices")
|
.with_tooltip("Service is running")
|
||||||
.with_icon(icon)
|
.with_icon(icon)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@ -100,7 +97,6 @@ pub struct TrayApp {
|
|||||||
device_manager: Arc<Mutex<DeviceManager>>,
|
device_manager: Arc<Mutex<DeviceManager>>,
|
||||||
devices: Arc<Mutex<HashMap<u32, MemoryDevice>>>,
|
devices: Arc<Mutex<HashMap<u32, MemoryDevice>>>,
|
||||||
tray_inner: TrayInner,
|
tray_inner: TrayInner,
|
||||||
notify: Arc<Notify>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -115,7 +111,6 @@ impl TrayApp {
|
|||||||
device_manager: Arc::new(Mutex::new(DeviceManager::new())),
|
device_manager: Arc::new(Mutex::new(DeviceManager::new())),
|
||||||
devices: Arc::new(Mutex::new(HashMap::new())),
|
devices: Arc::new(Mutex::new(HashMap::new())),
|
||||||
tray_inner: TrayInner::new(Arc::new(debug_console)),
|
tray_inner: TrayInner::new(Arc::new(debug_console)),
|
||||||
notify: Arc::new(Notify::new()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,7 +141,6 @@ impl TrayApp {
|
|||||||
fn spawn_device_fetch_thread(&self, proxy: EventLoopProxy<TrayEvent>) {
|
fn spawn_device_fetch_thread(&self, proxy: EventLoopProxy<TrayEvent>) {
|
||||||
let devices = Arc::clone(&self.devices);
|
let devices = Arc::clone(&self.devices);
|
||||||
let device_manager = Arc::clone(&self.device_manager);
|
let device_manager = Arc::clone(&self.device_manager);
|
||||||
let notify = Arc::clone(&self.notify);
|
|
||||||
|
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
let mut last_devices = HashSet::new();
|
let mut last_devices = HashSet::new();
|
||||||
@ -160,7 +154,6 @@ impl TrayApp {
|
|||||||
for id in removed_devices {
|
for id in removed_devices {
|
||||||
if let Some(device) = devices.remove(&id) {
|
if let Some(device) = devices.remove(&id) {
|
||||||
info!("Device removed: {}", device.name);
|
info!("Device removed: {}", device.name);
|
||||||
let _ = notify.device_disconnecred(&device.name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,7 +162,6 @@ impl TrayApp {
|
|||||||
if let Some(name) = device_manager.lock().get_device_name(id) {
|
if let Some(name) = device_manager.lock().get_device_name(id) {
|
||||||
devices.insert(id, MemoryDevice::new(name.clone(), id));
|
devices.insert(id, MemoryDevice::new(name.clone(), id));
|
||||||
info!("New device: {}", name);
|
info!("New device: {}", name);
|
||||||
let _ = notify.device_connected(&name);
|
|
||||||
} else {
|
} else {
|
||||||
error!("Failed to get device name for id: {}", id);
|
error!("Failed to get device name for id: {}", id);
|
||||||
}
|
}
|
||||||
@ -209,7 +201,6 @@ impl TrayApp {
|
|||||||
let tray_icon = Arc::clone(&self.tray_inner.tray_icon);
|
let tray_icon = Arc::clone(&self.tray_inner.tray_icon);
|
||||||
let debug_console = Arc::clone(&self.tray_inner.debug_console);
|
let debug_console = Arc::clone(&self.tray_inner.debug_console);
|
||||||
let menu_items = Arc::clone(&self.tray_inner.menu_items);
|
let menu_items = Arc::clone(&self.tray_inner.menu_items);
|
||||||
let notify = Arc::clone(&self.notify);
|
|
||||||
|
|
||||||
let menu_channel = MenuEvent::receiver();
|
let menu_channel = MenuEvent::receiver();
|
||||||
|
|
||||||
@ -221,7 +212,7 @@ impl TrayApp {
|
|||||||
TrayInner::build_tray(&tray_icon, &tray_menu, icon.clone());
|
TrayInner::build_tray(&tray_icon, &tray_menu, icon.clone());
|
||||||
}
|
}
|
||||||
tao::event::Event::UserEvent(TrayEvent::DeviceUpdate(device_ids)) => {
|
tao::event::Event::UserEvent(TrayEvent::DeviceUpdate(device_ids)) => {
|
||||||
Self::update(&devices, &device_manager, &device_ids, &tray_icon, ¬ify);
|
Self::update(&devices, &device_manager, &device_ids, &tray_icon);
|
||||||
}
|
}
|
||||||
tao::event::Event::UserEvent(TrayEvent::MenuEvent(event)) => {
|
tao::event::Event::UserEvent(TrayEvent::MenuEvent(event)) => {
|
||||||
let menu_items = menu_items.lock();
|
let menu_items = menu_items.lock();
|
||||||
@ -250,33 +241,11 @@ impl TrayApp {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_battery_icon(battery_level: i32, is_charging: bool) -> tray_icon::Icon {
|
|
||||||
let icon = match (battery_level, is_charging) {
|
|
||||||
(lvl, _) if lvl <= BATTERY_CRITICAL_LEVEL && !is_charging => {
|
|
||||||
include_bytes!("../assets/mouse_red.png").to_vec()
|
|
||||||
}
|
|
||||||
(lvl, _) if lvl <= BATTERY_LOW_LEVEL && !is_charging => {
|
|
||||||
include_bytes!("../assets/mouse_yellow.png").to_vec()
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => include_bytes!("../assets/mouse_white.png").to_vec(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let image = image::load_from_memory(&icon)
|
|
||||||
.expect("Failed to open icon")
|
|
||||||
.into_rgba8();
|
|
||||||
let (width, height) = image.dimensions();
|
|
||||||
let rgba = image.into_raw();
|
|
||||||
|
|
||||||
tray_icon::Icon::from_rgba(rgba, width, height).expect("Failed to create icon")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(
|
fn update(
|
||||||
devices: &Arc<Mutex<HashMap<u32, MemoryDevice>>>,
|
devices: &Arc<Mutex<HashMap<u32, MemoryDevice>>>,
|
||||||
manager: &Arc<Mutex<DeviceManager>>,
|
manager: &Arc<Mutex<DeviceManager>>,
|
||||||
device_ids: &[u32],
|
device_ids: &[u32],
|
||||||
tray_icon: &Arc<Mutex<Option<TrayIcon>>>,
|
tray_icon: &Arc<Mutex<Option<TrayIcon>>>,
|
||||||
notify: &Arc<Notify>,
|
|
||||||
) {
|
) {
|
||||||
let mut devices = devices.lock();
|
let mut devices = devices.lock();
|
||||||
let manager = manager.lock();
|
let manager = manager.lock();
|
||||||
@ -294,18 +263,7 @@ impl TrayApp {
|
|||||||
device.battery_level = battery_level;
|
device.battery_level = battery_level;
|
||||||
device.is_charging = is_charging;
|
device.is_charging = is_charging;
|
||||||
|
|
||||||
Self::check_notify(device, notify);
|
Self::check_notify(device);
|
||||||
|
|
||||||
if device.old_battery_level != battery_level
|
|
||||||
|| device.is_charging != is_charging
|
|
||||||
{
|
|
||||||
let new_icon = Self::get_battery_icon(battery_level, is_charging);
|
|
||||||
if let Some(tray_icon) = tray_icon.lock().as_mut() {
|
|
||||||
tray_icon
|
|
||||||
.set_icon(Some(new_icon))
|
|
||||||
.expect("Failed to update tray icon");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(tray_icon) = tray_icon.lock().as_mut() {
|
if let Some(tray_icon) = tray_icon.lock().as_mut() {
|
||||||
let _ = tray_icon
|
let _ = tray_icon
|
||||||
@ -316,18 +274,16 @@ impl TrayApp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_notify(device: &MemoryDevice, notify: &Notify) {
|
fn check_notify(device: &MemoryDevice) {
|
||||||
if device.battery_level == -1 {
|
if device.battery_level == -1 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !device.is_charging
|
if !device.is_charging
|
||||||
&& (device.battery_level <= BATTERY_CRITICAL_LEVEL
|
&& (device.battery_level <= 5
|
||||||
|| (device.old_battery_level > BATTERY_LOW_LEVEL
|
|| (device.old_battery_level > 15 && device.battery_level <= 15))
|
||||||
&& device.battery_level <= BATTERY_LOW_LEVEL))
|
|
||||||
{
|
{
|
||||||
info!("{}: Battery low ({}%)", device.name, device.battery_level);
|
info!("{}: Battery low ({}%)", device.name, device.battery_level);
|
||||||
let _ = notify.battery_low(&device.name, device.battery_level);
|
|
||||||
} else if device.old_battery_level <= 99
|
} else if device.old_battery_level <= 99
|
||||||
&& device.battery_level == 100
|
&& device.battery_level == 100
|
||||||
&& device.is_charging
|
&& device.is_charging
|
||||||
@ -336,7 +292,6 @@ impl TrayApp {
|
|||||||
"{}: Battery fully charged ({}%)",
|
"{}: Battery fully charged ({}%)",
|
||||||
device.name, device.battery_level
|
device.name, device.battery_level
|
||||||
);
|
);
|
||||||
let _ = notify.battery_full(&device.name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user