この記事のすべてのコードはGithubで入手できます。
準備する
AjentiをPyPIでダウンロードして解凍します。
依存関係をインストールします。
sudo pip install -Ur requirements.txt
さらに、 HTCPCP対応のコーヒーメーカーが必要です。お持ちでない場合は、ミルクとチョコレートの追加をサポートするシンプルなエミュレーターを使用できます。
HTCPCPクライアント
ajenti / pluginsにhtcpcpフォルダーを作成し、その中にプラグインのファイル構造を作成します。
ajenti/plugins/htcpcp ├── __init__.py ├── client.py └── layout └── config.xml
__Init__.pyには、プラグインに関する情報が含まれています。
from ajenti.api import * from ajenti.plugins import * info = PluginInfo( title='HTCPCP Example', icon='coffee', dependencies=[ PluginDependency('main') ], ) def init(): import client import main
client.pyで、HTCPCPプロトコルを操作するためのクラスを作成します。
import requests from ajenti.api import * from ajenti.plugins.configurator.api import ClassConfigEditor @plugin class HTCPCPClientConfigEditor (ClassConfigEditor): """ A plugin that handles editing of HTCPCPClient's classconfig """ title = 'HTCPCP Client' icon = 'coffee' def init(self): self.append(self.ui.inflate('htcpcp:config')) # htcpcp/layout/config.xml class CoffeeAddition (object): def __init__(self, name): self.name = name self.selected = False @plugin class HTCPCPClient (BasePlugin): classconfig_editor = HTCPCPClientConfigEditor # connect this plugin with a ConfigEditor default_classconfig = {'url': 'htcpcp://127.0.0.1:5000'} def init(self): self.additions = [] def check_connectivity(self): resp = requests.request('PROPFIND', self.get_url()) if resp.status_code == 418: raise Exception('This coffee pot is a teapot') def refresh(self): resp = requests.request('PROPFIND', self.get_url()) self.additions = [CoffeeAddition(x) for x in resp.headers['Additions-List'].split(';')] def get_url(self): return self.classconfig['url'].replace('htcpcp', 'http') def brew(self): """ Brew coffee with selected additions """ return requests.request('BREW', self.get_url(), headers={ 'Accept-Additions': ';'.join(x.name for x in self.additions if x.selected) }) def retrieve(self): return requests.request('GET', self.get_url())
ここでは、 ConfigEditor APIを使用して、ユーザーがHTCPCPClientクラスを再構成して別のコーヒーメーカーのURLを使用できるようにします。
パネルに空のセクションを作成します( main.py ):
from ajenti.api import * from ajenti.plugins.main.api import SectionPlugin from client import HTCPCPClient @plugin class CoffeePlugin (SectionPlugin): """ A HTCPCP capable coffeepot control plugin """ def init(self): self.title = 'Coffeepot' self.icon = 'coffee' self.category = _('System') # IoC: HTCPCPClient self.pot = HTCPCPClient.get()
クラスを構成してパネルを起動する小さなUIを追加します。
<bind:dict id="bind"> <!-- .classconfig --> <formline text="Coffeepot URL"> <textbox bind="url" /> </formline> </bind:dict>
make run
[Configure]> [Plugins]セクションに移動すると、プラグインが表示され、URLを構成できます。
インターフェース
美しいボタンを作成しましょう!
htcpcp / layout / main.xml :
<hc> <button id="brew" icon="arrow-right" text="Brew" /> <button id="retrieve" icon="coffee" text="Retrieve" /> <button id="refresh" icon="refresh" text="Refresh" /> </hc>
htcpcp / main.py :
from ajenti.api import * from ajenti.plugins.main.api import SectionPlugin from ajenti.ui import on from ajenti.ui.binder import Binder from client import HTCPCPClient @plugin class CoffeePlugin (SectionPlugin): """ A HTCPCP capable coffeepot control plugin """ def init(self): self.title = 'Coffeepot' self.icon = 'coffee' self.category = _('System') self.append(self.ui.inflate('htcpcp:main')) # htcpcp/layout/main.xml self.pot = HTCPCPClient.get() def on_page_load(self): try: self.pot.check_connectivity() except Exception, e: self.context.notify('error', 'Could not access the coffee pot: %s!' % str(e)) self.context.launch('configure-plugin', plugin=self.pot) # Configure @on('brew', 'click') def on_brew(self): resp = self.pot.brew() if resp.status_code == 200: self.context.notify('info', 'Brewing') else: self.context.notify('error', resp.text) @on('refresh', 'click') def on_refresh(self): # self.pot.refresh() @on('retrieve', 'click') def on_retrieve(self): resp = self.pot.retrieve() if resp.status_code == 200: self.context.notify('info', resp.text) else: self.context.notify('error', resp.text)
これで、ボタンを押してコーヒーを作ることができます:)
表示データ
サポートされているコーヒー添加物とその選択を表示するだけです。 このためには、 Binderクラスを直接使用してUIでデータバインディングを使用するのが最も便利です。
main.xml要素を追加して、添加剤のチェックボックスのリストを表示します。
<vc> <body> <pad id="pot-root"> <!-- id --> <bind:collection bind="additions"> <!-- CoffeeAdditions HTCPCPClient.additions --> <vc bind="__items"> <!-- <vc> --> <label style="bold" text="Available additions:" /> </vc> <bind:template> <!-- --> <checkbox bind:value="selected" bind:text="name" /> <!-- value addition.selected, text - c addition.name --> </bind:template> </bind:collection> </pad> </body> <hc> <button id="brew" icon="arrow-right" text="Brew" /> <button id="retrieve" icon="coffee" text="Retrieve" /> <button id="refresh" icon="refresh" text="Refresh" /> </hc> </vc>
そしてmain.pyでは、バインダーを使用してインターフェイスにデータを入力し、添加物の状態を更新します(チェックボックスの状態に基づいて選択または非選択)。
from ajenti.api import * from ajenti.plugins.main.api import SectionPlugin from ajenti.ui import on from ajenti.ui.binder import Binder from client import HTCPCPClient @plugin class CoffeePlugin (SectionPlugin): """ A HTCPCP capable coffeepot control plugin """ def init(self): self.title = 'Coffeepot' self.icon = 'coffee' self.category = _('System') self.append(self.ui.inflate('htcpcp:main')) self.pot = HTCPCPClient.get() # binder ( HTCPCPClient self.pot id=pot-root) self.binder = Binder(self.pot, self.find('pot-root')) def on_page_load(self): try: self.pot.check_connectivity() except Exception, e: self.context.notify('error', 'Could not access the coffee pot: %s!' % str(e)) self.context.launch('configure-plugin', plugin=self.pot) return if not self.pot.additions: # , self.pot.refresh() # UI self.binder.populate() @on('brew', 'click') def on_brew(self): # UI self.binder.update() resp = self.pot.brew() if resp.status_code == 200: self.context.notify('info', 'Brewing') else: self.context.notify('error', resp.text) @on('refresh', 'click') def on_refresh(self): self.pot.refresh() # UI self.binder.populate() @on('retrieve', 'click') def on_retrieve(self): resp = self.pot.retrieve() if resp.status_code == 200: self.context.notify('info', resp.text) else: self.context.notify('error', resp.text)
完了:)
この記事のコードはGithubで入手できることを思い出してください。また、ドキュメントを読んでサンプルを覗くことを忘れないでください。