moved code here. still needs to update gh

This commit is contained in:
klein panic
2025-02-24 15:18:44 -05:00
parent 9ca9f577a4
commit 2726432fe1
106 changed files with 4816 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
CC = gcc
CFLAGS = `pkg-config --cflags gtk+-3.0` -I$(INC_DIR)
LDFLAGS = `pkg-config --libs gtk+-3.0`
SRC_DIR = src
INC_DIR = include
OBJ_DIR = obj
OBJS = $(OBJ_DIR)/battery_monitor.o $(OBJ_DIR)/notification.o $(OBJ_DIR)/process_monitor.o
TARGET = battery_monitor
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
@mkdir -p $(OBJ_DIR)
$(CC) $(CFLAGS) -I$(INC_DIR) -o $@ -c $<
all: $(TARGET)
$(TARGET): $(OBJS)
$(CC) -o $(TARGET) $(OBJS) $(LDFLAGS)
clean:
rm -rf $(OBJ_DIR) $(TARGET)
.PHONY: all clean

View File

View File

@@ -0,0 +1,29 @@
#!/usr/bin/env bash
# Set up environment if needed
export DISPLAY=:0
export XAUTHORITY="$HOME/.Xauthority"
# Path to the battery monitor binary
BINARY_PATH="/usr/local/bin/battery_monitor"
# Log file
LOG_FILE="/tmp/battery_monitor.log"
# Create log directory if it doesn't exist
mkdir -p "$(dirname "$LOG_FILE")"
# Log starting message and environment variables
echo "Starting battery monitor script" >> "$LOG_FILE"
echo "DISPLAY=$DISPLAY" >> "$LOG_FILE"
echo "XAUTHORITY=$XAUTHORITY" >> "$LOG_FILE"
# Check if binary exists and is executable
if [ ! -x "$BINARY_PATH" ]; then
echo "Binary not found or not executable: $BINARY_PATH" >> "$LOG_FILE"
exit 1
fi
# Start the battery monitor and redirect output to log file
exec "$BINARY_PATH" >> "$LOG_FILE" 2>&1

Binary file not shown.

View File

@@ -0,0 +1,17 @@
[Unit]
Description=Battery Monitor Service
PartOf=graphical.target
After=graphical.target
[Service]
Type=simple
ExecStart=/usr/local/bin/battery_daemon.sh
Restart=always
Environment=DISPLAY=:0
Environment=XAUTHORITY=%h/.Xauthority
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=graphical.target

View File

@@ -0,0 +1,4 @@
Starting battery monitor script
DISPLAY=:0
XAUTHORITY=/home/klein/.Xauthority
Failed to open log file: Permission denied

View File

@@ -0,0 +1,16 @@
#ifndef BATTERY_MONITOR_H
#define BATTERY_MONITOR_H
void show_notification(const char *message, const char *title);
int get_battery_level();
int is_charging();
int activate_battery_saving_mode();
int enter_sleep_mode();
int kill_processes(const char *filename);
int set_brightness(int brightness);
void log_message(const char *message);
// New function declaration for process monitoring
int get_high_cpu_processes(char *process_list[], int max_processes);
#endif // BATTERY_MONITOR_H

View File

@@ -0,0 +1,8 @@
#ifndef PROCESS_MONITOR_H
#define PROCESS_MONITOR_H
int get_high_cpu_processes(char *process_list[], int max_processes);
void free_process_list(char *process_list[], int count);
#endif // PROCESS_MONITOR_H

View File

@@ -0,0 +1,63 @@
#!/usr/bin/env bash
# Function to check if a command exists
check_dependency() {
if ! command -v "$1" &> /dev/null; then
echo "$1 is not installed. Installing..."
sudo apt-get install -y "$1"
else
echo "$1 is already installed."
fi
}
# Step 1: Finding the current working directory and script location
SCRIPT_DIR=$(pwd)
BASH_SCRIPT="$SCRIPT_DIR/battery_daemon.sh"
SRC_SCRIPT="$SCRIPT_DIR/battery_monitor"
# Check if battery_daemon.sh exists
if [[ -f "$BASH_SCRIPT" ]]; then
echo "Found battery_daemon.sh. Moving to /usr/local/bin."
sudo cp "$BASH_SCRIPT" /usr/local/bin/battery_daemon.sh
sudo cp "$SRC_SCRIPT" /usr/local/bin/battery_monitor
sudo chmod +x /usr/local/bin/battery_daemon
sudo chmod +x /usr/local/bin/battery_daemon.sh
else
echo "battery_daemon.sh not found in the current directory!"
exit 1
fi
# Step 2: Check for dependencies and install if not present
dependencies=("gcc" "make" "brightnessctl")
for dep in "${dependencies[@]}"; do
check_dependency "$dep"
done
# Step 3: Copy battery_monitor.service to systemd folder
SYSTEMD_SERVICE="$SCRIPT_DIR/battery_monitor.service"
if [[ -f "$SYSTEMD_SERVICE" ]]; then
echo "Found battery_monitor.service. Copying to /etc/systemd/system/"
sudo cp "$SYSTEMD_SERVICE" /etc/systemd/system/
else
echo "battery_monitor.service not found in the current directory!"
exit 1
fi
# Step 4: Reload the systemd daemon, enable and restart the service
echo "Reloading systemd daemon..."
sudo systemctl daemon-reload
echo "Enabling battery_monitor.service..."
sudo systemctl enable battery_monitor.service
echo "Restarting battery_monitor.service..."
sudo systemctl restart battery_monitor.service
# Check if the service was successfully started
if systemctl is-active --quiet battery_monitor.service; then
echo "Service started successfully!"
else
echo "Failed to start the service."
exit 1
fi

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,70 @@
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include "battery_monitor.h"
// Define the battery thresholds
#define THRESHOLD_LOW 15
#define THRESHOLD_CRITICAL 5
#define THRESHOLD_HIGH 80
// Track if notifications have been sent
int notified_low = 0;
int notified_critical = 0;
int main() {
log_message("Battery monitor started");
while (1) {
if (is_charging()) {
// Reset notifications if the battery is charging
log_message("Battery is charging, notifications reset");
notified_low = 0;
notified_critical = 0;
sleep(300); // Sleep for 5 minutes while charging
continue;
}
int battery_level = get_battery_level();
if (battery_level == -1) {
log_message("Battery level read failed, retrying in 1 minute");
sleep(60);
continue;
}
// Dynamic sleep interval based on battery level
int sleep_duration = 60; // Default 1 minute
if (battery_level > THRESHOLD_HIGH) {
sleep_duration = 300; // Sleep for 5 minutes
} else if (battery_level <= THRESHOLD_CRITICAL) {
sleep_duration = 30; // Sleep for 30 seconds when critically low
} else if (battery_level <= THRESHOLD_LOW) {
sleep_duration = 60; // Sleep for 1 minute when low
}
// Check if the battery level is below the critical threshold
if (battery_level <= THRESHOLD_CRITICAL && !notified_critical) {
log_message("Battery critically low, showing notification");
show_notification("Battery is critically low, below 5%", "Critical Battery Warning");
notified_critical = 1;
} else if (battery_level <= THRESHOLD_LOW && !notified_low) {
log_message("Battery low, showing notification");
show_notification("Battery is low, below 15%", "Low Battery Warning");
notified_low = 1;
}
// Reset notifications if battery level goes back up
if (battery_level > THRESHOLD_LOW) {
notified_low = 0;
}
if (battery_level > THRESHOLD_CRITICAL) {
notified_critical = 0;
}
// Wait for the dynamically determined duration before checking again
sleep(sleep_duration);
}
return 0;
}

View File

@@ -0,0 +1,281 @@
#include <gtk/gtk.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <libgen.h>
#include "battery_monitor.h"
#include "process_monitor.h"
#define CSS_STYLE "\
* { \
background-color: #333333; \
color: white; \
} \
button { \
background-color: #555555; \
color: white; \
} \
"
// Function to get the battery level
int get_battery_level() {
const char *battery_paths[] = {
"/sys/class/power_supply/BAT0/capacity",
"/sys/class/power_supply/BAT1/capacity"
};
FILE *file;
int battery_level = -1;
for (int i = 0; i < sizeof(battery_paths) / sizeof(battery_paths[0]); i++) {
file = fopen(battery_paths[i], "r");
if (file != NULL) {
break;
}
}
if (file == NULL) {
perror("Failed to open capacity file");
log_message("Failed to open capacity file");
return -1;
}
if (fscanf(file, "%d", &battery_level) != 1) {
perror("Failed to read battery level");
log_message("Failed to read battery level");
fclose(file);
return -1;
}
fclose(file);
return battery_level;
}
// Function to get the base directory of the executable
char *get_base_directory() {
static char base_dir[PATH_MAX];
ssize_t count = readlink("/proc/self/exe", base_dir, PATH_MAX);
if (count != -1) {
dirname(base_dir);
}
return base_dir;
}
// Function to log messages to a file
void log_message(const char *message) {
char log_file[PATH_MAX];
snprintf(log_file, PATH_MAX, "/tmp/battery_monitor.log");
FILE *log_file_ptr = fopen(log_file, "a");
if (log_file_ptr) {
fprintf(log_file_ptr, "%s\n", message);
fclose(log_file_ptr);
} else {
perror("Failed to open log file");
}
}
// Function to activate battery saving mode
int activate_battery_saving_mode() {
log_message("Activating battery saving mode");
char process_list_file[PATH_MAX];
snprintf(process_list_file, PATH_MAX, "%s/../docs/process_list.txt", get_base_directory());
if (kill_processes(process_list_file) == -1) {
return -1; // Return failure if processes couldn't be killed
}
if (set_brightness(50) == -1) {
return -1; // Return failure if brightness couldn't be set
}
return 0; // Success
}
// Function to enter sleep mode
int enter_sleep_mode() {
log_message("Entering sleep mode");
return system("systemctl suspend"); // Return system command result
}
// Function to apply custom CSS styles to the GTK widgets
void apply_css(GtkWidget *widget, const char *css) {
GtkCssProvider *provider = gtk_css_provider_new();
gtk_css_provider_load_from_data(provider, css, -1, NULL);
GtkStyleContext *context = gtk_widget_get_style_context(widget);
gtk_style_context_add_provider(context, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_USER);
g_object_unref(provider);
}
// Function to check the battery status and close the dialog if charging
gboolean check_battery_status(gpointer user_data) {
GtkWidget *dialog = GTK_WIDGET(user_data);
if (is_charging()) {
log_message("Battery started charging, closing notification");
gtk_widget_destroy(dialog);
gtk_main_quit(); // Exit the GTK main loop
return FALSE; // Stop checking
}
return TRUE; // Continue checking
}
// Function to handle dialog response
void on_dialog_response(GtkDialog *dialog, gint response_id, gpointer user_data) {
switch (response_id) {
case GTK_RESPONSE_OK:
log_message("User clicked OK");
break;
case GTK_RESPONSE_APPLY:
log_message("User activated Battery Saving Mode");
activate_battery_saving_mode();
break;
case GTK_RESPONSE_CLOSE:
log_message("User triggered Sleep Mode");
enter_sleep_mode();
break;
default:
break;
}
gtk_widget_destroy(GTK_WIDGET(dialog));
gtk_main_quit(); // Exit the GTK main loop
}
// Function to show the notification dialog
void show_notification(const char *message, const char *title) {
log_message("Showing notification");
GtkWidget *dialog;
gtk_init(0, NULL);
dialog = gtk_message_dialog_new(NULL,
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_NONE,
"%s", message);
gtk_dialog_add_button(GTK_DIALOG(dialog), "OK", GTK_RESPONSE_OK);
gtk_dialog_add_button(GTK_DIALOG(dialog), "Battery Saving Mode", GTK_RESPONSE_APPLY);
if (g_strcmp0(title, "Critical Battery Warning") == 0) {
gtk_dialog_add_button(GTK_DIALOG(dialog), "Sleep", GTK_RESPONSE_CLOSE);
}
gtk_window_set_title(GTK_WINDOW(dialog), title);
// Apply CSS styles
apply_css(dialog, CSS_STYLE);
// Set up the callback to check battery status and close if charging
g_timeout_add(1000, check_battery_status, dialog);
// Connect the dialog response to handle button clicks and ensure proper cleanup
g_signal_connect(dialog, "response", G_CALLBACK(on_dialog_response), NULL);
// Show the dialog and enter the GTK main loop
gtk_widget_show_all(dialog);
gtk_main(); // Start the GTK main loop
}
// Function to check if the battery is charging
int is_charging() {
const char *status_paths[] = {
"/sys/class/power_supply/BAT0/status",
"/sys/class/power_supply/BAT1/status"
};
FILE *file;
char status[16];
for (int i = 0; i < sizeof(status_paths) / sizeof(status_paths[0]); i++) {
file = fopen(status_paths[i], "r");
if (file != NULL) {
break;
}
}
if (file == NULL) {
perror("Failed to open status file");
log_message("Failed to open status file");
return -1;
}
if (fscanf(file, "%15s", status) != 1) {
perror("Failed to read battery status");
log_message("Failed to read battery status");
fclose(file);
return -1;
}
fclose(file);
return (strcmp(status, "Charging") == 0);
}
// Function to kill processes based on a dynamic process list
int kill_processes(const char *filename) {
// Dynamic process list based on CPU usage
char *process_list[100]; // Assuming a max of 100 processes to kill
int process_count = get_high_cpu_processes(process_list, 100);
if (process_count == -1) {
log_message("Failed to get high CPU processes");
return -1;
}
for (int i = 0; i < process_count; i++) {
char command[300];
snprintf(command, sizeof(command), "pkill %s", process_list[i]);
log_message(command); // Log the command being executed
if (system(command) == -1) {
free_process_list(process_list, process_count);
return -1; // Return failure if the command fails
}
}
free_process_list(process_list, process_count);
return 0; // Success
}
// Function to set the screen brightness
int set_brightness(int brightness) {
const char *brightness_path = "/sys/class/backlight/intel_backlight/brightness";
const char *max_brightness_path = "/sys/class/backlight/intel_backlight/max_brightness";
int max_brightness = 100;
int new_brightness = 0;
char buffer[4];
int fd = open(max_brightness_path, O_RDONLY);
if (fd == -1) {
perror("Failed to open max brightness file");
log_message("Failed to open max brightness file");
return -1; // Return failure if the file can't be opened
}
if (read(fd, buffer, sizeof(buffer)) != -1) {
max_brightness = atoi(buffer);
} else {
perror("Failed to read max brightness");
log_message("Failed to read max brightness");
close(fd);
return -1; // Return failure if the file can't be read
}
close(fd);
new_brightness = max_brightness * brightness / 100;
fd = open(brightness_path, O_WRONLY);
if (fd == -1) {
perror("Failed to open brightness file");
log_message("Failed to open brightness file");
return -1; // Return failure if the file can't be opened
}
snprintf(buffer, sizeof(buffer), "%d", new_brightness);
if (write(fd, buffer, strlen(buffer)) == -1) {
perror("Failed to write to brightness file");
log_message("Failed to write to brightness file");
close(fd);
return -1; // Return failure if the write fails
}
close(fd);
return 0; // Success
}

View File

@@ -0,0 +1,143 @@
#include <gtk/gtk.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include "battery_monitor.h"
#define LOG_FILE "/home/klein/codeWS/C/bat0daemon/docs/battery_monitor.log"
void log_message(const char *message) {
FILE *log_file = fopen(LOG_FILE, "a");
if (log_file) {
fprintf(log_file, "%s\n", message);
fclose(log_file);
} else {
perror("Failed to open log file");
}
}
void activate_battery_saving_mode() {
log_message("Activating battery saving mode");
kill_processes("/home/klein/codeWS/C/bat0daemon/docs/procress_list.txt");
set_brightness(50);
}
void enter_sleep_mode() {
log_message("Entering sleep mode");
system("systemctl suspend");
}
void show_notification(const char *message, const char *title) {
log_message("Showing notification");
GtkWidget *dialog;
gtk_init(0, NULL);
dialog = gtk_message_dialog_new(NULL,
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_NONE,
"%s", message);
gtk_dialog_add_button(GTK_DIALOG(dialog), "OK", GTK_RESPONSE_OK);
gtk_dialog_add_button(GTK_DIALOG(dialog), "Battery Saving Mode", GTK_RESPONSE_APPLY);
if (g_strcmp0(title, "Critical Battery Warning") == 0) {
gtk_dialog_add_button(GTK_DIALOG(dialog), "Sleep", GTK_RESPONSE_CLOSE);
}
gtk_window_set_title(GTK_WINDOW(dialog), title);
gint response = gtk_dialog_run(GTK_DIALOG(dialog));
if (response == GTK_RESPONSE_APPLY) {
activate_battery_saving_mode();
} else if (response == GTK_RESPONSE_CLOSE) {
enter_sleep_mode();
}
gtk_widget_destroy(dialog);
while (g_main_context_iteration(NULL, FALSE));
}
int get_battery_level() {
FILE *file;
int battery_level = -1;
file = fopen("/sys/class/power_supply/BAT0/capacity", "r");
if (file == NULL) {
perror("Failed to open capacity file");
log_message("Failed to open capacity file");
return -1;
}
if (fscanf(file, "%d", &battery_level) != 1) {
perror("Failed to read battery level");
log_message("Failed to read battery level");
fclose(file);
return -1;
}
fclose(file);
return battery_level;
}
void kill_processes(const char *filename) {
FILE *file = fopen(filename, "r");
if (file == NULL) {
perror("Failed to open process list file");
log_message("Failed to open process list file");
return;
}
char process_name[256];
while (fgets(process_name, sizeof(process_name), file)) {
process_name[strcspn(process_name, "\n")] = 0; // Remove newline character
if (strlen(process_name) > 0) {
char command[300];
snprintf(command, sizeof(command), "pkill %s", process_name);
log_message(command); // Log the command being executed
system(command);
}
}
fclose(file);
}
void set_brightness(int brightness) {
const char *brightness_path = "/sys/class/backlight/intel_backlight/brightness";
const char *max_brightness_path = "/sys/class/backlight/intel_backlight/max_brightness";
int max_brightness = 100;
int new_brightness = 0;
char buffer[4];
int fd = open(max_brightness_path, O_RDONLY);
if (fd == -1) {
perror("Failed to open max brightness file");
log_message("Failed to open max brightness file");
return;
}
if (read(fd, buffer, sizeof(buffer)) != -1) {
max_brightness = atoi(buffer);
} else {
perror("Failed to read max brightness");
log_message("Failed to read max brightness");
}
close(fd);
new_brightness = max_brightness * brightness / 100;
fd = open(brightness_path, O_WRONLY);
if (fd == -1) {
perror("Failed to open brightness file");
log_message("Failed to open brightness file");
return;
}
snprintf(buffer, sizeof(buffer), "%d", new_brightness);
if (write(fd, buffer, strlen(buffer)) == -1) {
perror("Failed to write to brightness file");
log_message("Failed to write to brightness file");
}
close(fd);
}

View File

@@ -0,0 +1,45 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "battery_monitor.h"
#define BUFFER_SIZE 1024
int get_high_cpu_processes(char *process_list[], int max_processes) {
FILE *fp;
char buffer[BUFFER_SIZE];
int process_count = 0;
// Command to get the top CPU-using processes for the user 'klein', excluding vi, neovim, vim, and root processes
const char *command = "ps -eo user,pid,comm,%cpu --sort=-%cpu | grep '^klein' | grep -vE '(vi|vim|neovim|root)'";
fp = popen(command, "r");
if (fp == NULL) {
log_message("Failed to run command to get high CPU processes");
return -1;
}
while (fgets(buffer, sizeof(buffer), fp) != NULL && process_count < max_processes) {
char user[50], command_name[100];
int pid;
float cpu_usage;
// Parse the line to extract the user, PID, command name, and CPU usage
sscanf(buffer, "%49s %d %99s %f", user, &pid, command_name, &cpu_usage);
// Store the command in the process list
process_list[process_count] = malloc(BUFFER_SIZE);
snprintf(process_list[process_count], BUFFER_SIZE, "%d", pid);
process_count++;
}
pclose(fp);
return process_count;
}
void free_process_list(char *process_list[], int count) {
for (int i = 0; i < count; i++) {
free(process_list[i]);
}
}