Первую мою небольшую заметку по DataEngine можно найти здесь. Вообще, я не планировал продолжать эту тему. Но в процессе разработки было решено включить набор новых меток, например: загрузка GPU, температура GPU, температура HDD. В процессе реализации я столкнулся с некоторыми трудностями («плазма падает» ©), а в процессе поиска выхода из ситуации было решено создать новый DataEngine с блэкджеком и блудницами.
Для тех, кто что то пропустил. DataEngine — это специальный класс (plasmascript.DataEngine) в модуле PyKDE4. По сути — список словарей, каждый словарик при обращении к нему выдает какую то полезную информацию. Пожалуй, самые ходовые «словари» — systemmonitor и time, назначение обоих очевидно. Меня терзают смутные сомнения, что половина KDE4 так или иначе завязаны на работу этих самых DataEngine. Цель данного топика — создать свой DataEngine с нужными нам словарями.
Кого заинтересовало, прошу под хабракат.
Рассматривать будет все с точки зрения монитора температуры GPU, остальное делается легким движением руки (или пальцев) по образу и подобию. Приступим-с.
Вызовем нужные модули и объявим класс:
from PyQt4.QtCore import *
from PyKDE4.kdecore import *
from PyKDE4 import plasmascript
import commands
class ExtendedSysMon(plasmascript.DataEngine):
def __init__(self, parent, args=None):
"""dataengine definition"""
plasmascript.DataEngine.__init__(self, parent)
def init(self):
"""initialization"""
self.setMinimumPollingInterval(333)
# setup gpu device
self.gpudev = ''
commandOut = commands.getoutput("lspci")
if (commandOut.lower().find('nvidia') > -1):
self.gpudev = 'nvidia'
elif (commandOut.lower().find('radeon') > -1):
self.gpudev = 'ati'
Первые три модуля — для работы инструмента (engine), последний — для получения температуры. В __init__, как и все культурные люди ничего не делаем, кроме объявления. В init все довольно просто. Задаем минимальный интервал запросов (333) в мс, и определяем, какой девайс у нас стоит (nvidia или ati). Конечно, второе можно сделать лучше.
Создадим «сурсы» («словари»):
def sources(self):
"""create sources"""
sources = ["gputemp"]
return sources
def sourceRequestEvent(self, name):
return self.updateSourceEvent(name)
Запомнили (записали) наши source, нам по ним еще обращаться. Функция sourceRequestEvent обрабатывает наши (или не наши) запросы к словарям. Напишем теперь функцию, которая бы это все обрабатывала (updateSourceEvent):
def updateSourceEvent(self, source):
"""update sources and setup values"""
if (source == "gputemp"):
if (self.gpudev == 'nvidia'):
commandOut = commands.getoutput("nvidia-smi -q -d TEMPERATURE | grep Gpu | tail -n1")
try:
value = "%4s" % (str(round(float(commandOut.split()[2]), 1)))
except:
value = " NA"
elif (self.gpudev == 'ati'):
commandOut = commands.getoutput("aticonfig --od-gettemperature | grep Temperature | tail -n1")
try:
value = "%4s" % (str(round(float(commandOut.split()[4]), 1)))
except:
value = " NA"
else:
value = " NA"
self.setData(source, "GPUTemp", QString(value))
return True
Все просто и интуитивно понятно. Получаем строку, парсим ее, вытаскиваем циферку и передаем в словарик. Немного про функцию self.setData(). Имеет три параметра: source (имя словаря, к которому обращаемся, QString), ключ словаря (QString) и значение, соответствующее данному ключу (можно int, можно float или еще что нибудь, тут QString). Замечу, что как и в других нормальных словарях, ключей может быть несколько — так можно создать один source под температуру HDD, в котором 3 ключа — на 3 жестких диска. Ах да, try...except — это для того, чтобы не устраивать унылые проверки наличия ПО/видеокарты и проч. Если source'ов будет много — делаем конструкцию if...elif....
Ну все, скрипт почти готов:
def CreateDataEngine(parent):
return ExtendedSysMon(parent)
Теперь оформим это все красиво:
$ ls -R extsysmon
extsysmon:
contents metadata.desktop
extsysmon/contents:
code
extsysmon/contents/code:
main.py
Меня терзают смутные сомнения (исходники листал), что если Вы положите main.py в любую другую директорию, то ничего не запустится, хотя как будто бы все рабочее. И создадим metadata.desktop:
[Desktop Entry]
Encoding=UTF-8
Name=Extended SystemMonitor DataEngine
Comment=Adds gpu, gputemp and hddtemp to DataEngine
ServiceTypes=Plasma/DataEngine
Type=Service
Icon=utilities-system-monitor
X-Plasma-API=python
X-Plasma-MainScript=code/main.py
X-KDE-PluginInfo-Author=%username%
X-KDE-PluginInfo-Email=%e-mail%
X-KDE-PluginInfo-Name=ext-sysmon
X-KDE-PluginInfo-Version=1.0
X-KDE-PluginInfo-Website=http://kde-look.org/
X-KDE-PluginInfo-Category=System Information
X-KDE-PluginInfo-Depends=
X-KDE-PluginInfo-License=GPL
X-KDE-PluginInfo-EnabledByDefault=true
Принципиально важно тут — ServiceTypes, X-Plasma-API, X-Plasma-MainScript. Первый — указывает тип (DataEngine), второй — шелл, третий — путь к исходному скрипту (исключая contents). Остальное понятно, как и везде.
Архивируем (из рабочей директории):
zip -qr extsysmon.zip contents metadata.desktop
Устанавливаем:
plasmapkg -t dataengine -i extsysmon.zip
Говорят, указать тип (-t dataengine) здесь обязательно, иначе виджетом определит.
…
PROFIT!
Красивая картинка, все работает:
Загрузка GPU у меня не определяется, а температуры GPU нет, т.к. дискретная видеокарта выключена.
Исходный код доступен на github. Подключение инструмента и работа с ним — в первой заметке.
Автор: arcan1s