Skip to content

Commit

Permalink
feat: Track battery level in systray (#1)
Browse files Browse the repository at this point in the history
* track mouse battery level in systray

* update `ReadMe.md`
  • Loading branch information
ugurcandede authored Oct 29, 2024
1 parent b776d6b commit 7a0deff
Show file tree
Hide file tree
Showing 5 changed files with 251 additions and 106 deletions.
1 change: 1 addition & 0 deletions .idea/battery_indicator.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 11 additions & 5 deletions ReadMe.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ the battery percentage and the charging status.
## Requirements

- Python 3.x
- `hid` library (can be installed via pip)
- `hidapi` library (can be installed via pip)
- `pystray` library (can be installed via pip)

## Installation

Expand All @@ -37,16 +38,21 @@ pip install -r requirements.txt

## Usage

Run the script to check the battery status of the connected SteelSeries Rival 650 Wireless mouse. The output will
display the battery percentage and whether the device is currently charging.
Run the script to check the battery status of the connected SteelSeries Rival 650 Wireless mouse. An icon will be
displayed in the system tray.

```bash
python battery_monitor.py
python main.py
```

## Output

The main script executed an icon will be displayed in the system tray.

Otherwise, if `_init.py` is executed, will output the battery percentage and the charging status of the device. The
output will be as follows:

```
SteelSeries Rival 650 Wireless (wired mode) | 75% and it is charging
SteelSeries Rival 650 Wireless (2.4GHz wireless mode) | 50% and is not charging
```
```
120 changes: 120 additions & 0 deletions _init.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Author: Ugurcan Dede
Date: 2024-10-28
GitHub: https://github.com/ugurcandede
Description:
This script prints the battery level of the SteelSeries Rival 650 Wireless mouse to the console.
It utilizes the 'hid' library to communicate with the device and retrieves battery information through HID reports.
The program opens a connection to the mouse, sends a command to request the battery level, and processes the response
to determine the battery percentage and charging status.
Usage:
Run this script to check the battery status of the connected SteelSeries Rival 650 Wireless mouse. The output will
display the battery percentage and whether the device is currently charging.
"""

import hid

import rival650


def _load_models():
return [
{
"name": model["name"],
"vendor_id": model["vendor_id"],
"product_id": model["product_id"],
"endpoint": model["endpoint"]
}
for model in rival650.profile["models"]
]


class DeviceManager:
def __init__(self):
self.models = _load_models()
self.exists_model = self.find_exits_model()

def open_device(self, vendor_id, product_id, endpoint=0):
hid_device = hid.device()
for interface in hid.enumerate(vendor_id, product_id):
if interface["interface_number"] == endpoint and interface["usage"] == 1:
hid_device.open_path(interface["path"])
return HIDDevice(hid_device, vendor_id, product_id, endpoint)
raise Exception("No device found")

def find_exits_model(self):
for model in self.models:
for interface in hid.enumerate(model['vendor_id'], model['product_id']):
if interface["interface_number"] == model['endpoint'] and interface["usage"] == 1:
return model


class HIDDevice:
def __init__(self, device, vendor_id, product_id, endpoint):
self.device = device
self.vendor_id = vendor_id
self.product_id = product_id
self.endpoint = endpoint

def hid_write(self, report_type=rival650.HID_REPORT_TYPE_OUTPUT, report_id=0x00, data=[], packet_length=0):
if packet_length > 0:
bytes_ = bytearray([report_id] + data + [0x00] * (packet_length - 1 - len(data)))
else:
bytes_ = bytearray([report_id] + data)

if report_type == rival650.HID_REPORT_TYPE_OUTPUT:
self.device.write(bytes_)
else:
raise ValueError(f"Invalid HID report type: {report_type:02x}")

def read(self, response_length, timeout_ms=200):
return self.device.read(response_length, timeout_ms)

def close(self):
self.device.close()


class BatteryStatus:
def __init__(self, device_manager):
self.device_manager = device_manager

def get_status(self):
status = {}
for model in self.device_manager.models:
hid_device = None
try:
hid_device = self.device_manager.open_device(model['vendor_id'], model['product_id'], model['endpoint'])
hid_device.hid_write(
report_type=rival650.profile["battery_level"]["report_type"],
data=rival650.profile["battery_level"]["command"]
)
data = hid_device.read(rival650.profile["battery_level"]["response_length"])

status.update({
"name": model['name'],
"battery": rival650.profile["battery_level"]["level"](data),
"charging": rival650.profile["battery_level"]["is_charging"](data)
})

except Exception:
pass
finally:
if hid_device is not None:
hid_device.close()
if len(status) == 0:
status.update({"name": "No device found", "battery": None, "charging": None})
return status


if __name__ == '__main__':
device_manager = DeviceManager()
battery_status = BatteryStatus(device_manager)

device = battery_status.get_status()
print(f"{device['name']} | %{device['battery']} and it is {'charging' if device['charging'] else 'not charging'}")
Loading

0 comments on commit 7a0deff

Please sign in to comment.