Evgenii Legotckoi
Evgenii Legotckoi1. April 2017 12:16

Qt Linux - Lektion 003. Überprüfen des Akkuladestands des Laptops mit libacpi

Im Forum gab es ein Gespräch darüber, den Akkustand eines Laptops unter Linux mit der Qt-Bibliothek zu überprüfen. Tatsächlich stellt Qt derzeit keine Klasse zur Verfügung, mit der Sie den Ladezustand des Akkus überprüfen können, aber solche Funktionen können mithilfe von Bibliotheken von Drittanbietern wie libacpi. implementiert werden.

Versuchen wir, eine Anwendung zu erstellen, die zumindest einige Daten benötigt und wie folgt aussieht:


libacpi

Die Bibliothek selbst ist in C geschrieben und hat die folgenden interessanten Funktionen und Datenstrukturen:

  • global_t - globale Datenstruktur, die die Anzahl der Lüfter, Batterien und Wärmezonen sowie die Struktur mit dem Netzteil speichert.
  • init_acpi_batt(global_t *globals) - Batteriedateninitialisierung
  • init_acpi_acadapt(global_t *globals) - Adapterdaten initialisieren
  • init_acpi_fan(global_t *globals) - Lüfterdateninitialisierung
  • init_acpi_thermal(global_t *globals) - Initialisierung von Daten zu thermischen Zonen
  • read_acpi_batt(int num) - Batteriedaten lesen
  • read_acpi_zone(int num, global_t *globals) - Daten der thermischen Zone lesen
  • read_acpi_fan(int num) - Lüfterdaten lesen
  • battery_t - Batteriedatenstruktur
  • fans_t - Lüfterdatenstruktur
  • thermal_t - Datenstruktur der thermischen Zone
  • battery_t batteries [MAX_ITEMS] - ein Array von Batterien, Daten werden darin gespeichert, wenn read_acpi_batt aufgerufen wird
  • thermal_t thermals [MAX_ITEMS] - Array von thermischen Zonen, Daten werden darin gespeichert, wenn read_acpi_zone aufgerufen wird
  • fan_t fans [MAX_ITEMS] - Fans-Array, Daten werden darin gespeichert, wenn read_acpi_fan aufgerufen wird

Verwenden der Bibliothek

Um die Bibliothek in einem Qt-Projekt zu verwenden, müssen Sie:

  1. Installieren Sie die Bibliothek aus dem Repository:
sudo apt-get install libacpi-dev
  1. Verbinden Sie die Bibliothek in der Pro-Projektdatei:
LIBS += -lacpi
  1. Verbinden Sie die Header-Datei der Bibliothek mit der Quellcode-Datei, wo sie Daten über die Batterieladung erhält:
#ifdef __cplusplus
extern "C" {
#endif

#include <libacpi.h>

#ifdef __cplusplus
}
#endif

Hauptanwendungsfenster

Das Hauptanwendungsfenster ist eine Widget-Klasse, die mit einer ui-Datei erstellt wird und deren Schnittstelle von einem Grafikdesigner erstellt wird. Es hat eine ScrollArea, die ein Objekt der vertikalen Platzierung von Elementen enthält, Widgets, die dynamisch erstellt werden, je nachdem, was die Bibliothek finden konnte. Und es gibt auch eine Schaltfläche zum Starten des Lesens von Daten durch die Bibliothek.

Widget.h

Die Header-Datei deklariert Vektoren mit Widgets für Batterien, Lüfter und thermische Zonen. Außerdem wird ein Zeiger auf ein Widget mit Netzteil deklariert. Alle Widgets sind benutzerdefinierte Klassen. Etwas weiter unten wird der Code eines der Widgets als Beispiel angegeben.

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

#include "batterywidget.h"
#include "adapterwidget.h"
#include "fanwidget.h"
#include "thermalwidget.h"

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private slots:
    void on_pushButton_clicked();

private:
    Ui::Widget *ui;
    QVector<BatteryWidget*> m_butteryWidgetList;    // Вектор виджетов с батареями
    QVector<FanWidget*> m_fanWidgetList;            // Вектор виджетов с вентиляторами
    QVector<ThermalWidget*> m_thermalWidgetList;    // Вектор виджетов с тепловыми зонами
    AdapterWidget* m_adapterWidget;                 // Виджет для адаптера питания всегда один
};

#endif // WIDGET_H

Widget.cpp

Da die Bibliothek in C geschrieben ist, hat sie einen prozeduralen Codeausführungsstil. Es gibt auch einen kleinen Trick. Tatsache ist, dass die Bibliothek mehrere globale Variablen hat, in die Daten geschrieben werden. Dies sind Arrays mit Lüftern, thermischen Zonen und Batterien.

Das heißt, wenn Sie die Funktion read_acpi_batt(1) aufrufen, schreiben Sie die Datenstruktur battery_t in die Zelle des Arrays batteries[1]. .

Um eine globale Struktur zu erstellen, die Daten über die Anzahl aller oben genannten Strukturen enthält, ist es jedoch erforderlich, Speicher zuzuweisen.

#include "widget.h"
#include "ui_widget.h"

#ifdef __cplusplus
extern "C" {
#endif

#include <libacpi.h>

#ifdef __cplusplus
}
#endif

#include <QFileDialog>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget),
    m_adapterWidget(nullptr)
{
    ui->setupUi(this);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::on_pushButton_clicked()
{
    // Выделяем память под глобальную структуру данных бибилотеки
    global_t *global = static_cast<global_t*>(malloc(sizeof(global_t)));

    // Инициализируем структуру для
    init_acpi_batt(global);     // батареи
    init_acpi_acadapt(global);  // адаптера питания
    init_acpi_fan(global);      // вентиляторов
    init_acpi_thermal(global);  // тепловых зон

    // Battery
    battery_t *binfo;

    // Если нашлись батареи, то считываем в цикле данные и добавляем виджеты
    for(int i=0; i < global->batt_count; i++)
    {
        read_acpi_batt(i);      // считываем данные
        // которые считываются в специальный массив batteries - он есть в самой библиотеке
        binfo = &batteries[i];

        BatteryWidget* butteryWidget;
        // Создаём виджет
        if (m_butteryWidgetList.count() <= i)
        {
            butteryWidget = new BatteryWidget(this);
            butteryWidget->setTitle(QString(binfo->name));
            m_butteryWidgetList.append(butteryWidget);
            ui->verticalLayout->addWidget(butteryWidget);
        }
        else
        {
            // Или забираем его из списка виджетов
            butteryWidget = m_butteryWidgetList.at(i);
        }

        // Устанавливаем
        butteryWidget->setPercentage(binfo->percentage);        // Процент заряда
        butteryWidget->setChargeTime(binfo->charge_time);       // Время до полного заряда
        butteryWidget->setRemainingTime(binfo->remaining_time); // Время до полного разряда

        // Определяем статус заряда
        switch (binfo->charge_state)
        {
        case C_CHARGE:
            butteryWidget->setChargeState("Charging");
            break;
        case C_DISCHARGE:
            butteryWidget->setChargeState("Discharging");
        case C_CHARGED:
            butteryWidget->setChargeState("Charged");
        case C_NOINFO:
            butteryWidget->setChargeState("No info");
        default:
            butteryWidget->setChargeState("Error");
            break;
        }
    }

    // Adapter
    // Настройка виджета для адптера питания
    adapter_t *ac = &global->adapt;

    if (!m_adapterWidget)
    {
        m_adapterWidget = new AdapterWidget(this);
        ui->verticalLayout->addWidget(m_adapterWidget);
    }

    // Здесь проверяем только, подключён или нет
    switch (ac->ac_state)
    {
    case P_AC:
        m_adapterWidget->setStatus("Runs on AC");
        break;
    case P_BATT:
        m_adapterWidget->setStatus("Runs on battery");
    default:
        m_adapterWidget->setStatus("Error");
        break;
    }

    // Fan
    fan_t *finfo;

    // Если нашлись вентиляторы, то считываем в цикле данные и добавляем виджеты
    for(int i=0; i < global->fan_count; i++)
    {
        read_acpi_fan(i);   // считываем данные
        // которые считываются в специальный массив fans - он есть в самой библиотеке
        finfo = &fans[i];
        FanWidget* fanWidget;

        // Создаём виджет
        if (m_fanWidgetList.count() <= i)
        {
            fanWidget = new FanWidget(this);
            fanWidget->setTitle(QString(finfo->name));
            m_fanWidgetList.append(fanWidget);
            ui->verticalLayout->addWidget(fanWidget);
        }
        else
        {
            // Или забираем его из списка виджетов
            fanWidget = m_fanWidgetList.at(i);
        }

        // Устанавливаем статус, включён или нет
        switch (finfo->fan_state)
        {
        case F_ON:
            fanWidget->setStatus("ON");
            break;
        case F_OFF:
            fanWidget->setStatus("OFF");
        default:
            fanWidget->setStatus("Error");
            break;
        }
    }

    // Thermal
    thermal_t *tinfo;

    // Если нашлись тепловые зоны, то считываем в цикле данные и добавляем виджеты
    for(int i=0; i < global->fan_count; i++)
    {
        read_acpi_zone(i, global);  // считываем данные
        // которые считываются в специальный массив thermals - он есть в самой библиотеке
        tinfo = &thermals[i];
        ThermalWidget* thermalWidget;

        // Создаём виджет
        if (m_thermalWidgetList.count() <= i)
        {
            thermalWidget = new ThermalWidget(this);
            thermalWidget->setTitle(QString(tinfo->name));
            m_thermalWidgetList.append(thermalWidget);
            ui->verticalLayout->addWidget(thermalWidget);
        }
        else
        {
            // Или забираем его из списка виджетов
            thermalWidget = m_thermalWidgetList.at(i);
        }

        thermalWidget->setTemperature(tinfo->temperature);  // Устанавливаем температуру
        thermalWidget->setFrequency(tinfo->frequency);      // и частоту
    }

    free(global);
}

Widgets

Das Programm enthält Widgets für alle oben genannten Strukturen. Sie dienen lediglich dazu, Informationen anzuzeigen und dynamisch hinzuzufügen. Ich werde als Beispiel ein Widget geben, das Informationen über die Batterie anzeigt.

Batterie-Widget.h

#ifndef BATTERYWIDGET_H
#define BATTERYWIDGET_H

#include <QWidget>

namespace Ui {
class BatteryWidget;
}

class BatteryWidget : public QWidget
{
    Q_OBJECT

public:
    explicit BatteryWidget(QWidget *parent = 0);
    ~BatteryWidget();

    void setTitle(QString title);               // Название батареи (как определено в ОС Linux)
    void setPercentage(int percentage);         // Процент заряда
    void setChargeTime(int chargeTime);         // Время до полного заряда в минутах
    void setRemainingTime(int remainingTime);   // Время до полного разряда в минутах
    void setChargeState(QString chargeState);   // Состояние

private:
    Ui::BatteryWidget *ui;
};

#endif // BATTERYWIDGET_H

Batteriewidget.cpp

#include "batterywidget.h"
#include "ui_batterywidget.h"

BatteryWidget::BatteryWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::BatteryWidget)
{
    ui->setupUi(this);
}

BatteryWidget::~BatteryWidget()
{
    delete ui;
}

void BatteryWidget::setTitle(QString title)
{
    ui->label_title->setText(title);
}

void BatteryWidget::setPercentage(int percentage)
{
    ui->label_percentage->setText(QString::number(percentage));
}

void BatteryWidget::setChargeTime(int chargeTime)
{
    ui->label_charge_time->setText(QString("%1:%2").arg(chargeTime / 60).arg(chargeTime % 60));
}

void BatteryWidget::setRemainingTime(int remainingTime)
{
    ui->label_remaining_time->setText(QString("%1:%2").arg(remainingTime / 60).arg(remainingTime % 60));
}

void BatteryWidget::setChargeState(QString chargeState)
{
    ui->label_charge_state->setText(chargeState);
}

Das Ergebnis der Bibliothek

Ich würde das Ergebnis der Arbeit der Bibliothek als zufriedenstellend bezeichnen, obwohl es den Prozentsatz der Batterieladung sowie die Zeit zum vollständigen Aufladen der Batterie bestimmt. Aber sie hat die Zeit vor der Entlassung nicht bestimmt. Und auch keine Lüfter und Wärmezonen gefunden. Ich glaube, dass auf meinem Laptop-Modell diese Daten einfach nicht verfügbar sind. Es gab auch periodische Abstürze der Anwendung beim Versuch, auf einige Strukturparameter zuzugreifen.

Der Screenshot am Anfang des Artikels zeigt die Daten, die die Bibliothek in meinem Laptop finden konnte. Natürlich sind dort nicht alle Daten angegeben, wenn Sie sich die Header-Datei der Bibliothek ansehen, werden Sie feststellen, dass die Strukturen eine reichhaltigere Auswahl an Parametern bieten. Aber ich denke, das reicht aus, um den Start der Bibliothek zu demonstrieren.

Versuchen Sie, das Projekt selbst auszuführen, und melden Sie sich nach Möglichkeit ab, wenn diese Bibliothek thermische Zonen und Lüfter in Ihrem Laptop findet.

Antragsentwurf

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Stabiles Hosting des sozialen Netzwerks EVILEG. Wir empfehlen VDS-Hosting für Django-Projekte.

Magst du es? In sozialen Netzwerken teilen!

Kommentare

Nur autorisierte Benutzer können Kommentare posten.
Bitte Anmelden oder Registrieren
Letzte Kommentare
ИМ
Игорь Максимов5. Oktober 2024 07:51
Django – Lektion 064. So schreiben Sie eine Python-Markdown-Erweiterung Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas55. Juli 2024 11:02
QML - Lektion 016. SQLite-Datenbank und das Arbeiten damit in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
k
kmssr8. Februar 2024 18:43
Qt Linux - Lektion 001. Autorun Qt-Anwendung unter Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
Qt WinAPI - Lektion 007. Arbeiten mit ICMP-Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVA25. Dezember 2023 10:30
Boost - statisches Verknüpfen im CMake-Projekt unter Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
Jetzt im Forum diskutieren
J
JacobFib17. Oktober 2024 03:27
добавить qlineseries в функции Пользователь может получить любые разъяснения по интересующим вопросам, касающимся обработки его персональных данных, обратившись к Оператору с помощью электронной почты https://topdecorpro.ru…
JW
Jhon Wick1. Oktober 2024 15:52
Indian Food Restaurant In Columbus OH| Layla’s Kitchen Indian Restaurant If you're looking for a truly authentic https://www.laylaskitchenrestaurantohio.com/ , Layla’s Kitchen Indian Restaurant is your go-to destination. Located at 6152 Cleveland Ave, Colu…
КГ
Кирилл Гусарев27. September 2024 09:09
Не запускается программа на Qt: точка входа в процедуру не найдена в библиотеке DLL Написал программу на C++ Qt в Qt Creator, сбилдил Release с помощью MinGW 64-bit, бинарнику напихал dll-ки с помощью windeployqt.exe. При попытке запуска моей сбилженной программы выдаёт три оши…
F
Fynjy22. Juli 2024 04:15
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …

Folgen Sie uns in sozialen Netzwerken