Skocz do zawartości

Recommended Posts

Napisano

Powoli zaczynam rozumieć, jak działa Rust.

Chcę napisać swoją pierwszą aplikację do obsługi myszy Razer Trinity w systemie Linux. Aplikacja musi umożliwiać: wykrywanie zmian panelu bocznego myszy, tworzenie profili dla konkretnych paneli, przypisywanie profili do programów oraz aktywację profilu podczas pracy z przypisanym do niego programem. Próbowałem zrobić to w Pythonie, ale utknąłem w martwym punkcie.

Teraz postanowiłem spróbować sił w języku Rust.

Muszę zaznaczyć, że jestem w tym języku zupełnie początkujący, ale postawiłem sobie to wyzwanie, by się go nauczyć. Na razie dysponuję kodem zamieszczonym poniżej; nie komunikuje się on jeszcze z właściwym sterownikiem myszy (rolę „sterownika” pełni na razie zwykły plik tekstowy), ale pętla działa poprawnie. Jeśli chodzi o OpenRazer, to niestety nie wykrywa on zmian panelu bocznego w tym modelu myszy, więc zamierzam spróbować obsłużyć to bezpośrednio, odczytując dane z `hidraw`.

Korzystam z pomocy sztucznej inteligencji przy tworzeniu aplikacji, ale nie zlecam jej napisania całego kodu; używam jej raczej do zrozumienia struktury języka i uzyskiwania sugestii dotyczących rozwiązań.

Oto dotychczasowe efekty – to mój pierwszy dzień programowania, choć spędziłem już około 10 godzin na analizie materiałów o języku Rust dostępnych w sieci. Dajcie znać, co o tym sądzicie i czy macie jakieś pomysły.

Z góry dziękuję za pomoc.

 

// Importujemy potrzebne narzędzia z biblioteki standardowej Rusta (std)
use std::fs;                  // fs - do pracy z plikami (zapis/odczyt)
use std::thread::sleep;       // sleep - do wstrzymywania działania programu
use std::time::Duration;      // Duration - do określania czasu (np. sekundy)

/// 1. DEFINICJE TYPÓW DANYCH (Poza funkcją main)

// Enum (typ wyliczeniowy) reprezentuje zamkniętą listę możliwości.
// Makro #[derive(...)] automatycznie generuje dodatkowe funkcjonalności:
// - Debug: pozwala na wypisywanie enuma w konsoli za pomocą {:?}
// - PartialEq: pozwala na porównywanie wartości za pomocą "=="
// - Clone: umożliwia tworzenie kopii tego obiektu w pamięci
#[derive(Debug, PartialEq, Clone)]
enum TypPanelu {
    DwaPrzyciski,
    SiedemPrzyciskow,
    DwanasciePrzyciskow,
}

// Struktura to kontener łączący różne powiązane ze sobą dane.
#[derive(Debug, Clone)]
struct Profil {
    nazwa: String,        // Ludzka nazwa profilu
    program: String,      // Nazwa procesu/programu (np. "csgo")
    typ_panelu: TypPanelu, // Jaki panel jest wymagany dla tego profilu (używamy enuma powyżej)
}

/// 2. GŁÓWNA FUNKCJA PROGRAMU
fn main() {
    // Tworzymy przykładowy profil. 
    // String::from() jest potrzebne, bo tekst w cudzysłowie to tzw. &str (niezmienny wycinek),
    // a nasza struktura wymaga pełnoprawnego, modyfikowalnego obiektu typu String.
    let profil_do_gier = Profil {
        nazwa: String::from("Profil do CS-a"),
        program: String::from("csgo"),
        typ_panelu: TypPanelu::SiedemPrzyciskow,
    };

    // Wypisujemy informacje startowe w konsoli
    println!("Wczytano profil: {} (Wymaga panelu: {:?})", profil_do_gier.nazwa, profil_do_gier.typ_panelu);
    println!("--- Uruchamiam monitorowanie myszki ---");

    // Zmienna mutowalna (mut), która służy jako "pamięć" programu.
    // Przechowuje stan panelu z poprzedniej sekundy, dzięki czemu program 
    // nie wyświetla komunikatów cały czas, a reaguje TYLKO na zmiany.
    let mut poprzedni_panel = String::new();

    // Uruchamiamy nieskończoną pętlę (tzw. demon lub usługa w tle)
    loop {
        // Próba odczytania pliku tekstowego symulującego sterownik.
        // fs::read_to_string zwraca typ Result (sukces lub błąd), dlatego musimy użyć 'match'.
        let wynik_czytania = fs::read_to_string("C:\\Users\\Adam Graszk\\zgadywanka\\razer_panel.txt");

        match wynik_czytania {
            // PRZYPADEK 1: Plik udało się odczytać, a jego zawartość trafia do zmiennej `zawartosc`
            Ok(zawartosc) => {
                // .trim() usuwa białe znaki z początku i końca (np. spacja lub znak nowej linii \n)
                let oczyszczony_tekst = zawartosc.trim();

                // Sprawdzamy, czy obecna zawartość pliku różni się od tego, co zapamiętaliśmy sekundę temu
                if oczyszczony_tekst != poprzedni_panel {
                    
                    // Drugi match: sprawdzamy co dokładnie znajduje się w pliku
                    match oczyszczony_tekst {
                        "2" => println!("Wykryto panel z 2 przyciskami!"),
                        "7" => println!("Wykryto panel z 7 przyciskami!"),
                        "12" => println!("Wykryto panel z 12 przyciskami!"),
                        // Gwiazdka/podkreślenie (_) to tzw. catch-all. Obsługuje każdy inny tekst
                        _ => println!("Nieznany panel lub brak panelu!"),
                    }
                    
                    // Aktualizujemy naszą "pamięć" o nowy stan panelu, konwertując &str na String
                    poprzedni_panel = oczyszczony_tekst.to_string();
                }
            }
            // PRZYPADEK 2: Nie udało się odczytać pliku (np. został usunięty lub brak uprawnień)
            // Podkreślenie przed '_blad' mówi kompilatorowi, że wiemy o istnieniu błędu, ale go ignorujemy.
            Err(_blad) => {
                println!("Ostrzeżenie: Nie można odczytać sterownika. Próba za sekundę...");
                // Resetujemy pamięć, aby po naprawieniu błędu program na nowo wykrył panel
                poprzedni_panel = String::new(); 
            }
        }

        // Wstrzymujemy działanie pętli na 1 sekundę, aby program nie zużywał 100% mocy procesora
        sleep(Duration::from_secs(1));       
    }
}

 
 
 

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Gość
Odpowiedz...

×   Wkleiłeś zawartość bez formatowania.   Usuń formatowanie

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Utwórz nowe...