HTCPCPを介したAjentiコーヒーメーカーのWebインターフェイス

コーヒーを求めて走り回り、コーヒーメーカーのボタンを押すのにうんざりしていませんか? Webインターフェイスを作成してください!











この記事のすべてのコードは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で入手できることを思い出してください。また、ドキュメントを読んサンプルを覗くこと忘れないでください。



All Articles