Загрузка данных


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/input.h>
#include <sys/select.h>
#include <sys/time.h>
#include <string.h>
#include <errno.h>
#include <dirent.h>
#include <time.h>
#include <sys/stat.h>

// Константы
#define SIGNAL_FILE "/tmp/signalS"  // Файл сигнала для управления программой
#define SENSOR_FILE "/tmp/mySensors"  // Файл с данными датчиков
#define SCRIPT_PATH "/home/diver/Скрипты/sensors.sh"  // Скрипт для получения данных датчиков
#define IDLE_TIMEOUT 60  // Время бездействия перед переходом в спящий режим (секунды)
#define TIMEOUT 1  // Таймаут проверки активности устройств (секунды)
#define TEMP_CHECK_INTERVAL 5  // Интервал проверки температуры при превышении (секунды)
#define BRIGHTNESS_LOW 60  // Минимальная яркость экрана
#define BRIGHTNESS_OFF 0  // Выключенная яркость экрана
#define TEMP_THRESHOLD 60  // Пороговая температура для изменения частоты процессора
#define FREQ_LOW "1100MHz"  // Низкая частота процессора
#define FREQ_HIGH "3.0GHz"  // Высокая частота процессора

char *MOUSE_DEVICE = NULL;
char *KEYBOARD_DEVICE = NULL;

// Функция для выполнения внешних команд
void run_command(const char *command) {
    FILE *fp = popen(command, "r");
    if (!fp) {
        fprintf(stderr, "Не удалось выполнить команду: %s\n", command);
        return;
    }
    char buffer[128];
    while (fgets(buffer, sizeof(buffer), fp)) {
        printf("%s", buffer);
    }
    pclose(fp);
}

// Функция для проверки активности устройства
int check_device_activity(const char *device_path, int timeout) {
    int fd = open(device_path, O_RDONLY | O_NONBLOCK);
    if (fd < 0) {
        perror("Не удалось открыть устройство");
        return 0;
    }

    fd_set fds;
    FD_ZERO(&fds);
    FD_SET(fd, &fds);

    struct timeval tv = {timeout, 0};

    int ret = select(fd + 1, &fds, NULL, NULL, &tv);
    close(fd);

    if (ret > 0) {
        return 1; // Есть активность
    }

    return 0; // Нет активности
}

// Функция для проверки работы mpv
int is_mpv_running() {
    DIR *dir = opendir("/proc");
    if (!dir) {
        perror("Не удалось открыть /proc");
        return 0;
    }

    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) {
        if (entry->d_type == DT_DIR) {
            char path[256];
            snprintf(path, sizeof(path), "/proc/%s/comm", entry->d_name);
            FILE *fp = fopen(path, "r");
            if (fp) {
                char comm[16];
                if (fgets(comm, sizeof(comm), fp)) {
                    if (strncmp(comm, "mpv", 3) == 0) {
                        fclose(fp);
                        closedir(dir);
                        return 1;
                    }
                }
                fclose(fp);
            }
        }
    }
    closedir(dir);
    return 0;
}

// Функция для установки яркости экрана
void set_screen_brightness(int level) {
    char command[64];
    snprintf(command, sizeof(command), "xbacklight -set %d", level);
    run_command(command);
}

// Получение текущей частоты процессора
void get_current_cpu_frequency() {
    printf("Текущая частота процессора:\n");
    run_command("cpupower frequency-info | grep 'current CPU freq'");
}

// Функция для автоматического поиска устройств ввода через libinput
char* find_input_device(const char* capability_keyword, const char* name_keyword) {
    FILE *fp = popen("libinput list-devices", "r");
    if (!fp) {
        perror("Не удалось выполнить libinput list-devices");
        return NULL;
    }

    char line[512];
    char name[256] = {0};
    char kernel[256] = {0};
    char scroll_methods[256] = {0};
    int has_capability = 0;
    int is_excluded = 0;

    while (fgets(line, sizeof(line), fp)) {
        // Начало новой секции устройства — сброс всех флагов
        if (strncmp(line, "Device:", 7) == 0) {
            // Сброс флагов
            memset(name, 0, sizeof(name));
            memset(kernel, 0, sizeof(kernel));
            memset(scroll_methods, 0, sizeof(scroll_methods));
            has_capability = 0;
            is_excluded = 0;

            // Парсим имя устройства
            sscanf(line, "Device:                  %[^\n]", name);
            // Исключаем устройства с "Keyboard" в имени для мыши
            if (strcmp(capability_keyword, "pointer") == 0 && strstr(name, "Keyboard")) {
                is_excluded = 1;
            }
        }

        // Парсинг пути устройства
        else if (strncmp(line, "Kernel:", 7) == 0) {
            sscanf(line, "Kernel:                  %s", kernel);
        }

        // Проверка возможностей
        else if (strstr(line, "Capabilities:") && strstr(line, capability_keyword)) {
            has_capability = 1;
        }

        // Проверка методов прокрутки (признак мыши)
        else if (strstr(line, "Scroll methods:")) {
            sscanf(line, "Scroll methods:          %[^\n]", scroll_methods);
        }

        // Конец секции устройства — проверка условий
        else if (line[0] == '\n') {
            // Для мыши: требуется Scroll methods = button
            if (strcmp(capability_keyword, "pointer") == 0) {
                if (has_capability && !is_excluded &&
                    strstr(scroll_methods, "button") && kernel[0] != '\0') {
                    char *device_path = strdup(kernel);
                    pclose(fp);
                    return device_path;
                }
            }

            // Для клавиатуры: исключаем системные устройства
            else if (strcmp(capability_keyword, "keyboard") == 0) {
                if (has_capability && !is_excluded && kernel[0] != '\0') {
                    if ((name_keyword == NULL) || (strstr(name, name_keyword))) {
                        char *device_path = strdup(kernel);
                        pclose(fp);
                        return device_path;
                    }
                }
            }
        }
    }

    pclose(fp);
    return NULL;
}

// Основная функция
int main() {
    // Автоматическое определение устройств
    KEYBOARD_DEVICE = find_input_device("keyboard", "Keyboard");
    MOUSE_DEVICE = find_input_device("pointer", "Mouse|TouchPad");

    if (!MOUSE_DEVICE || !KEYBOARD_DEVICE) {
        fprintf(stderr, "Не удалось найти устройства ввода\n");
        free(MOUSE_DEVICE);
        free(KEYBOARD_DEVICE);
        return 1;
    }

    printf("Найдена клавиатура: %s\n", KEYBOARD_DEVICE);
    printf("Найдена мышь: %s\n", MOUSE_DEVICE);

    // Проверка и создание сигнального файла
    if (access(SIGNAL_FILE, F_OK) == 0) {
        remove(SIGNAL_FILE);
        printf("Сигнальный файл удален. Выход.\n");
        free(MOUSE_DEVICE);
        free(KEYBOARD_DEVICE);
        return 0;
    }

    FILE *file = fopen(SIGNAL_FILE, "w");
    if (!file) {
        perror("Не удалось создать сигнальный файл");
        free(MOUSE_DEVICE);
        free(KEYBOARD_DEVICE);
        return 1;
    }
    fclose(file);

    // Проверка доступности устройств
    if (access(MOUSE_DEVICE, F_OK) != 0) {
        printf("Устройство мыши не найдено!\n");
        free(MOUSE_DEVICE);
        free(KEYBOARD_DEVICE);
        return 1;
    }
    if (access(KEYBOARD_DEVICE, F_OK) != 0) {
        printf("Устройство клавиатуры не найдено!\n");
        free(MOUSE_DEVICE);
        free(KEYBOARD_DEVICE);
        return 1;
    }

    // Основной цикл
    time_t last_activity_time = time(NULL);  // Время последней активности
    int in_sleep_mode = 0;  // Флаг спящего режима
    int in_game_mode = 0;   // Флаг игрового режима
    int temp_throttle_active = 0;  // Флаг активного режима снижения частоты из-за температуры
    int current_interval = TIMEOUT;  // Текущий интервал проверки

    while (access(SIGNAL_FILE, F_OK) == 0) {
        printf("\n--- Новая итерация ---\n");

        // Проверка активности
        int mouse_active = check_device_activity(MOUSE_DEVICE, TIMEOUT);
        int keyboard_active = check_device_activity(KEYBOARD_DEVICE, TIMEOUT);
        int mpv_active = is_mpv_running();

        // Обновление времени последней активности
        if (mouse_active || keyboard_active || mpv_active) {
            last_activity_time = time(NULL);
            if (in_sleep_mode) {
                printf("Активность обнаружена. Возобновление нормального режима.\n");
                in_sleep_mode = 0;
                set_screen_brightness(BRIGHTNESS_LOW);

                // Если выходим из спящего режима, восстанавливаем частоту процессора
                printf("Восстановление частоты процессора до стандартных значений...\n");
                run_command("cpupower frequency-set -g powersave -d 800MHz -u 4.0GHz");
                get_current_cpu_frequency();
                temp_throttle_active = 0;
                current_interval = TIMEOUT;
            }
        }

        // Проверка времени бездействия
        if (!in_sleep_mode && (time(NULL) - last_activity_time) >= IDLE_TIMEOUT) {
            printf("Нет активности более %d секунд. Переход в спящий режим...\n", IDLE_TIMEOUT);
            in_sleep_mode = 1;
            set_screen_brightness(BRIGHTNESS_OFF);

            // В спящем режиме принудительно устанавливаем частоту процессора на 800 МГц
            printf("Принудительное снижение частоты процессора до 800 МГц...\n");
            run_command("cpupower frequency-set -g powersave -d 800MHz -u 800MHz");
            get_current_cpu_frequency();
            temp_throttle_active = 0;
            current_interval = TIMEOUT;
        }

        // Проверка игрового режима
        if (mpv_active) {
            if (!in_game_mode) {
                printf("Обнаружен игровой режим (mpv запущен).\n");
                in_game_mode = 1;
            }
        } else {
            if (in_game_mode) {
                printf("Игровой режим завершен (mpv остановлен).\n");
                in_game_mode = 0;

                // При выходе из игрового режима восстанавливаем частоту процессора
                printf("Восстановление частоты процессора после игрового режима...\n");
                run_command("cpupower frequency-set -g powersave -d 800MHz -u 4.0GHz");
                get_current_cpu_frequency();
                temp_throttle_active = 0;
                current_interval = TIMEOUT;
            }
        }

        // Проверка температуры
        if (!in_sleep_mode) {
            system("sensors | grep 'Core 0:' | awk '{print $3}' | sed 's/[+°C]//g' > /tmp/mySensors");
            FILE *sensor_file = fopen(SENSOR_FILE, "r");
            if (sensor_file) {
                char buffer[32];
                if (fgets(buffer, sizeof(buffer), sensor_file)) {
                    float temperature = atof(buffer);
                    printf("Текущая температура: %.2f°C\n", temperature);

                    // Проверка на превышение порога
                    if (temperature >= TEMP_THRESHOLD) {
                        printf("Температура %.2f°C превышает порог %d°C! Снижение частоты до %s...\n",
                               temperature, TEMP_THRESHOLD, FREQ_LOW);
                        
                        // Снижаем частоту
                        char command[128];
                        snprintf(command, sizeof(command),
                            "cpupower frequency-set -g powersave -d 800MHz -u %s", FREQ_LOW);
                        run_command(command);
                        get_current_cpu_frequency();
                        
                        temp_throttle_active = 1;
                        current_interval = TEMP_CHECK_INTERVAL;
                        printf("Таймер увеличен до %d секунд\n", TEMP_CHECK_INTERVAL);
                        
                    } else if (temp_throttle_active) {
                        // Температура нормализовалась после троттлинга
                        printf("Температура нормализовалась (%.2f°C). Восстановление частоты до %s...\n", 
                               temperature, FREQ_HIGH);
                        
                        char command[128];
                        snprintf(command, sizeof(command),
                            "cpupower frequency-set -g powersave -d 800MHz -u %s", FREQ_HIGH);
                        run_command(command);
                        get_current_cpu_frequency();
                        
                        temp_throttle_active = 0;
                        current_interval = TIMEOUT;
                        printf("Таймер возвращен на %d секунду\n", TIMEOUT);
                        
                    } else {
                        printf("Температура %.2f°C в пределах нормы.\n", temperature);
                    }
                } else {
                    printf("Не удалось прочитать данные из файла сенсоров.\n");
                }
                fclose(sensor_file);
            } else {
                printf("Не удалось открыть файл сенсоров.\n");
            }
        }

        // Спим нужный интервал
        sleep(current_interval);
    }

    printf("Сигнальный файл удален. Выход.\n");

    // Очистка памяти
    free(MOUSE_DEVICE);
    free(KEYBOARD_DEVICE);

    return 0;
}