Standards & Guideliens

This commit is contained in:
manuel83 2018-12-10 22:29:27 +01:00
parent fc65d3e33e
commit a8060fff08
6 changed files with 161 additions and 49 deletions

View file

@ -2,19 +2,7 @@
<project version="4"> <project version="4">
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="1a245e6a-2e43-4348-8759-dc1b63a4c9c8" name="Default" comment="Lots of changes"> <list default="true" id="1a245e6a-2e43-4348-8759-dc1b63a4c9c8" name="Default" comment="Lots of changes">
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/core/api/step.py" afterPath="$PROJECT_DIR$/core/api/step.py" /> <change type="MODIFICATION" beforePath="$PROJECT_DIR$/docs_src/source/standards.rst" afterPath="$PROJECT_DIR$/docs_src/source/standards.rst" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/core/controller/crud_controller.py" afterPath="$PROJECT_DIR$/core/controller/crud_controller.py" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/core/controller/notification_controller.py" afterPath="$PROJECT_DIR$/core/controller/notification_controller.py" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/core/controller/plugin_controller.py" afterPath="$PROJECT_DIR$/core/controller/plugin_controller.py" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/core/controller/step_controller.py" afterPath="$PROJECT_DIR$/core/controller/step_controller.py" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/core/craftbeerpi.py" afterPath="$PROJECT_DIR$/core/craftbeerpi.py" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/core/extension/dummystep/__init__.py" afterPath="$PROJECT_DIR$/core/extension/dummystep/__init__.py" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/docs/_sources/step.rst.txt" afterPath="$PROJECT_DIR$/docs/_sources/step.rst.txt" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/docs/genindex.html" afterPath="$PROJECT_DIR$/docs/genindex.html" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/docs/index.html" afterPath="$PROJECT_DIR$/docs/index.html" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/docs/step.html" afterPath="$PROJECT_DIR$/docs/step.html" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/docs_src/source/index.rst" afterPath="$PROJECT_DIR$/docs_src/source/index.rst" />
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/docs_src/source/step.rst" afterPath="$PROJECT_DIR$/docs_src/source/step.rst" />
</list> </list>
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" /> <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="TRACKING_ENABLED" value="true" /> <option name="TRACKING_ENABLED" value="true" />
@ -87,18 +75,6 @@
</component> </component>
<component name="FileEditorManager"> <component name="FileEditorManager">
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300"> <leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
<file leaf-file-name="__init__.py" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/core/extension/dummystep/__init__.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="315">
<caret line="21" column="52" lean-forward="false" selection-start-line="21" selection-start-column="52" selection-end-line="21" selection-end-column="52" />
<folding>
<element signature="e#0#14#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file leaf-file-name="step.py" pinned="false" current-in-tab="false"> <file leaf-file-name="step.py" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/core/api/step.py"> <entry file="file://$PROJECT_DIR$/core/api/step.py">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
@ -114,8 +90,8 @@
<file leaf-file-name="actor_controller.py" pinned="false" current-in-tab="false"> <file leaf-file-name="actor_controller.py" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/core/controller/actor_controller.py"> <entry file="file://$PROJECT_DIR$/core/controller/actor_controller.py">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="327"> <state relative-caret-position="300">
<caret line="95" column="4" lean-forward="false" selection-start-line="95" selection-start-column="4" selection-end-line="96" selection-end-column="51" /> <caret line="20" column="39" lean-forward="false" selection-start-line="12" selection-start-column="4" selection-end-line="20" selection-end-column="39" />
<folding> <folding>
<element signature="e#0#23#0" expanded="true" /> <element signature="e#0#23#0" expanded="true" />
</folding> </folding>
@ -146,8 +122,18 @@
<file leaf-file-name="standards.rst" pinned="false" current-in-tab="true"> <file leaf-file-name="standards.rst" pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/docs_src/source/standards.rst"> <entry file="file://$PROJECT_DIR$/docs_src/source/standards.rst">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="105"> <state relative-caret-position="725">
<caret line="7" column="0" lean-forward="true" selection-start-line="7" selection-start-column="0" selection-end-line="7" selection-end-column="0" /> <caret line="75" column="32" lean-forward="false" selection-start-line="75" selection-start-column="32" selection-end-line="75" selection-end-column="32" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="requirements.txt" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/requirements.txt">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="300">
<caret line="20" column="13" lean-forward="false" selection-start-line="20" selection-start-column="13" selection-end-line="20" selection-end-column="13" />
<folding /> <folding />
</state> </state>
</provider> </provider>
@ -1200,14 +1186,13 @@
</component> </component>
<component name="ToolWindowManager"> <component name="ToolWindowManager">
<frame x="522" y="154" width="2415" height="1447" extended-state="0" /> <frame x="522" y="154" width="2415" height="1447" extended-state="0" />
<editor active="true" />
<layout> <layout>
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.3286945" sideWeight="0.5" order="10" side_tool="false" content_ui="tabs" /> <window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.3286945" sideWeight="0.5" order="10" side_tool="false" content_ui="tabs" />
<window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.43208432" sideWeight="0.2720238" order="0" side_tool="true" content_ui="tabs" /> <window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.43208432" sideWeight="0.2720238" order="0" side_tool="true" content_ui="tabs" />
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.14441219" sideWeight="0.7279762" order="6" side_tool="false" content_ui="tabs" /> <window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.14441219" sideWeight="0.7279762" order="6" side_tool="false" content_ui="tabs" />
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.3286945" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" /> <window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.3286945" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Python Console" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.3290398" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" /> <window_info id="Python Console" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.3290398" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
<window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.31712627" sideWeight="0.49761903" order="3" side_tool="false" content_ui="tabs" /> <window_info id="Terminal" active="true" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.31712627" sideWeight="0.49761903" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.1573499" sideWeight="0.5" order="1" side_tool="false" content_ui="combo" /> <window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.1573499" sideWeight="0.5" order="1" side_tool="false" content_ui="combo" />
<window_info id="Database" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.067908905" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" /> <window_info id="Database" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.067908905" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.3256785" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" /> <window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.3256785" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
@ -1265,16 +1250,6 @@
</watches-manager> </watches-manager>
</component> </component>
<component name="editorHistoryManager"> <component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/core/websocket.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="106">
<caret line="23" column="8" lean-forward="false" selection-start-line="23" selection-start-column="8" selection-end-line="23" selection-end-column="69" />
<folding>
<element signature="e#0#14#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/core/api/decorator.py"> <entry file="file://$PROJECT_DIR$/core/api/decorator.py">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="174"> <state relative-caret-position="174">
@ -1752,18 +1727,26 @@
</entry> </entry>
<entry file="file://$PROJECT_DIR$/core/controller/actor_controller.py"> <entry file="file://$PROJECT_DIR$/core/controller/actor_controller.py">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="327"> <state relative-caret-position="300">
<caret line="95" column="4" lean-forward="false" selection-start-line="95" selection-start-column="4" selection-end-line="96" selection-end-column="51" /> <caret line="20" column="39" lean-forward="false" selection-start-line="12" selection-start-column="4" selection-end-line="20" selection-end-column="39" />
<folding> <folding>
<element signature="e#0#23#0" expanded="true" /> <element signature="e#0#23#0" expanded="true" />
</folding> </folding>
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/requirements.txt">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="300">
<caret line="20" column="13" lean-forward="false" selection-start-line="20" selection-start-column="13" selection-end-line="20" selection-end-column="13" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/docs_src/source/standards.rst"> <entry file="file://$PROJECT_DIR$/docs_src/source/standards.rst">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="105"> <state relative-caret-position="725">
<caret line="7" column="0" lean-forward="true" selection-start-line="7" selection-start-column="0" selection-end-line="7" selection-end-column="0" /> <caret line="75" column="32" lean-forward="false" selection-start-line="75" selection-start-column="32" selection-end-line="75" selection-end-column="32" />
<folding /> <folding />
</state> </state>
</provider> </provider>

View file

@ -4,7 +4,8 @@ Standard & Guidelines
Python Python
^^^^^^ ^^^^^^
CraftBeerPi 4.x is based on Pyhton 3.7x. as main frameworks is `aiohttp` used. CraftBeerPi 4.x is based on Pyhton 3.7x.
As a main framework CraftBeerPi is based on `aiohttp`
* aioHTTP https://aiohttp.readthedocs.io/en/stable/ * aioHTTP https://aiohttp.readthedocs.io/en/stable/
@ -36,6 +37,49 @@ Here an example how listen on an event.
It's imporante to add **kwargs as parameter to the listening method. This makes sure that maybe addtional event paramenter are not causing an exception. It's imporante to add **kwargs as parameter to the listening method. This makes sure that maybe addtional event paramenter are not causing an exception.
HTTP Endpoints
--------------
A new HTTP endpoints should be exposed by adding the `@request_mapping` decorator on top of an async method.
The `path` parameter defines the URL path. The `auth_required` defines whether the endpoint should be accessible public or within a user session only.
Typically you perform just some basing parameter validation and fire an event so that other components and controllers can perform some actions.
.. code-block:: python
@request_mapping(path="/{id:\d+}/on", auth_required=False)
async def http_on(self, request) -> web.Response:
self.cbpi.bus.fire(topic="actor/%s/switch/on" % id, id=id, power=99)
return web.Response(status=204)
.. note::
The Events are process in an async way. Results will be pushed to the client via WebSocket Event.
WebSocket
---------
The WebSocket is listening on `http://<IP_ADDRESS>:<PORT>/ws`
All events are forwarded to all connected web socket clients.
The WebSocket Event is having the following structure.
* topic -> is the bus topic
* data -> the event data
.. code-block:: json
{
"topic":"notification/step",
"data":{
"key":"step",
"message":"Hello World",
"type":"info"
}
}
Web User Interface Web User Interface
^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^
The Web UI is based on ReactJS + Redux. The Web UI is based on ReactJS + Redux.

View file

@ -188,6 +188,8 @@
<li class="toctree-l1"><a class="reference internal" href="standards.html">Standard &amp; Guidelines</a><ul> <li class="toctree-l1"><a class="reference internal" href="standards.html">Standard &amp; Guidelines</a><ul>
<li class="toctree-l2"><a class="reference internal" href="standards.html#python">Python</a><ul> <li class="toctree-l2"><a class="reference internal" href="standards.html#python">Python</a><ul>
<li class="toctree-l3"><a class="reference internal" href="standards.html#eventbus">EventBus</a></li> <li class="toctree-l3"><a class="reference internal" href="standards.html#eventbus">EventBus</a></li>
<li class="toctree-l3"><a class="reference internal" href="standards.html#http-endpoints">HTTP Endpoints</a></li>
<li class="toctree-l3"><a class="reference internal" href="standards.html#websocket">WebSocket</a></li>
</ul> </ul>
</li> </li>
<li class="toctree-l2"><a class="reference internal" href="standards.html#web-user-interface">Web User Interface</a></li> <li class="toctree-l2"><a class="reference internal" href="standards.html#web-user-interface">Web User Interface</a></li>

File diff suppressed because one or more lines are too long

View file

@ -88,6 +88,8 @@
<li class="toctree-l1 current"><a class="current reference internal" href="#">Standard &amp; Guidelines</a><ul> <li class="toctree-l1 current"><a class="current reference internal" href="#">Standard &amp; Guidelines</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#python">Python</a><ul> <li class="toctree-l2"><a class="reference internal" href="#python">Python</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#eventbus">EventBus</a></li> <li class="toctree-l3"><a class="reference internal" href="#eventbus">EventBus</a></li>
<li class="toctree-l3"><a class="reference internal" href="#http-endpoints">HTTP Endpoints</a></li>
<li class="toctree-l3"><a class="reference internal" href="#websocket">WebSocket</a></li>
</ul> </ul>
</li> </li>
<li class="toctree-l2"><a class="reference internal" href="#web-user-interface">Web User Interface</a></li> <li class="toctree-l2"><a class="reference internal" href="#web-user-interface">Web User Interface</a></li>
@ -162,7 +164,8 @@
<h1>Standard &amp; Guidelines<a class="headerlink" href="#standard-guidelines" title="Permalink to this headline"></a></h1> <h1>Standard &amp; Guidelines<a class="headerlink" href="#standard-guidelines" title="Permalink to this headline"></a></h1>
<div class="section" id="python"> <div class="section" id="python">
<h2>Python<a class="headerlink" href="#python" title="Permalink to this headline"></a></h2> <h2>Python<a class="headerlink" href="#python" title="Permalink to this headline"></a></h2>
<p>CraftBeerPi 4.x is based on Pyhton 3.7x. as main frameworks is <cite>aiohttp</cite> used.</p> <p>CraftBeerPi 4.x is based on Pyhton 3.7x.
As a main framework CraftBeerPi is based on <cite>aiohttp</cite></p>
<ul class="simple"> <ul class="simple">
<li>aioHTTP <a class="reference external" href="https://aiohttp.readthedocs.io/en/stable/">https://aiohttp.readthedocs.io/en/stable/</a></li> <li>aioHTTP <a class="reference external" href="https://aiohttp.readthedocs.io/en/stable/">https://aiohttp.readthedocs.io/en/stable/</a></li>
</ul> </ul>
@ -186,6 +189,42 @@ This makes sure that all components are loosely coupled. New plugins can listen
<p class="last">Its imporante to add <a href="#id1"><span class="problematic" id="id2">**</span></a>kwargs as parameter to the listening method. This makes sure that maybe addtional event paramenter are not causing an exception.</p> <p class="last">Its imporante to add <a href="#id1"><span class="problematic" id="id2">**</span></a>kwargs as parameter to the listening method. This makes sure that maybe addtional event paramenter are not causing an exception.</p>
</div> </div>
</div> </div>
<div class="section" id="http-endpoints">
<h3>HTTP Endpoints<a class="headerlink" href="#http-endpoints" title="Permalink to this headline"></a></h3>
<p>A new HTTP endpoints should be exposed by adding the <cite>&#64;request_mapping</cite> decorator on top of an async method.
The <cite>path</cite> parameter defines the URL path. The <cite>auth_required</cite> defines whether the endpoint should be accessible public or within a user session only.
Typically you perform just some basing parameter validation and fire an event so that other components and controllers can perform some actions.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="nd">@request_mapping</span><span class="p">(</span><span class="n">path</span><span class="o">=</span><span class="s2">&quot;/{id:\d+}/on&quot;</span><span class="p">,</span> <span class="n">auth_required</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span>
<span class="n">async</span> <span class="k">def</span> <span class="nf">http_on</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">request</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">web</span><span class="o">.</span><span class="n">Response</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">cbpi</span><span class="o">.</span><span class="n">bus</span><span class="o">.</span><span class="n">fire</span><span class="p">(</span><span class="n">topic</span><span class="o">=</span><span class="s2">&quot;actor/</span><span class="si">%s</span><span class="s2">/switch/on&quot;</span> <span class="o">%</span> <span class="nb">id</span><span class="p">,</span> <span class="nb">id</span><span class="o">=</span><span class="nb">id</span><span class="p">,</span> <span class="n">power</span><span class="o">=</span><span class="mi">99</span><span class="p">)</span>
<span class="k">return</span> <span class="n">web</span><span class="o">.</span><span class="n">Response</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="mi">204</span><span class="p">)</span>
</pre></div>
</div>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">The Events are process in an async way. Results will be pushed to the client via WebSocket Event.</p>
</div>
</div>
<div class="section" id="websocket">
<h3>WebSocket<a class="headerlink" href="#websocket" title="Permalink to this headline"></a></h3>
<p>The WebSocket is listening on <cite>http://&lt;IP_ADDRESS&gt;:&lt;PORT&gt;/ws</cite>
All events are forwarded to all connected web socket clients.</p>
<p>The WebSocket Event is having the following structure.</p>
<ul class="simple">
<li>topic -&gt; is the bus topic</li>
<li>data -&gt; the event data</li>
</ul>
<div class="highlight-json notranslate"><div class="highlight"><pre><span></span><span class="p">{</span>
<span class="nt">&quot;topic&quot;</span><span class="p">:</span><span class="s2">&quot;notification/step&quot;</span><span class="p">,</span>
<span class="nt">&quot;data&quot;</span><span class="p">:{</span>
<span class="nt">&quot;key&quot;</span><span class="p">:</span><span class="s2">&quot;step&quot;</span><span class="p">,</span>
<span class="nt">&quot;message&quot;</span><span class="p">:</span><span class="s2">&quot;Hello World&quot;</span><span class="p">,</span>
<span class="nt">&quot;type&quot;</span><span class="p">:</span><span class="s2">&quot;info&quot;</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
</div>
</div> </div>
<div class="section" id="web-user-interface"> <div class="section" id="web-user-interface">
<h2>Web User Interface<a class="headerlink" href="#web-user-interface" title="Permalink to this headline"></a></h2> <h2>Web User Interface<a class="headerlink" href="#web-user-interface" title="Permalink to this headline"></a></h2>

View file

@ -4,7 +4,8 @@ Standard & Guidelines
Python Python
^^^^^^ ^^^^^^
CraftBeerPi 4.x is based on Pyhton 3.7x. as main frameworks is `aiohttp` used. CraftBeerPi 4.x is based on Pyhton 3.7x.
As a main framework CraftBeerPi is based on `aiohttp`
* aioHTTP https://aiohttp.readthedocs.io/en/stable/ * aioHTTP https://aiohttp.readthedocs.io/en/stable/
@ -36,6 +37,49 @@ Here an example how listen on an event.
It's imporante to add **kwargs as parameter to the listening method. This makes sure that maybe addtional event paramenter are not causing an exception. It's imporante to add **kwargs as parameter to the listening method. This makes sure that maybe addtional event paramenter are not causing an exception.
HTTP Endpoints
--------------
A new HTTP endpoints should be exposed by adding the `@request_mapping` decorator on top of an async method.
The `path` parameter defines the URL path. The `auth_required` defines whether the endpoint should be accessible public or within a user session only.
Typically you perform just some basing parameter validation and fire an event so that other components and controllers can perform some actions.
.. code-block:: python
@request_mapping(path="/{id:\d+}/on", auth_required=False)
async def http_on(self, request) -> web.Response:
self.cbpi.bus.fire(topic="actor/%s/switch/on" % id, id=id, power=99)
return web.Response(status=204)
.. note::
The Events are process in an async way. Results will be pushed to the client via WebSocket Event.
WebSocket
---------
The WebSocket is listening on `http://<IP_ADDRESS>:<PORT>/ws`
All events are forwarded to all connected web socket clients.
The WebSocket Event is having the following structure.
* topic -> is the bus topic
* data -> the event data
.. code-block:: json
{
"topic":"notification/step",
"data":{
"key":"step",
"message":"Hello World",
"type":"info"
}
}
Web User Interface Web User Interface
^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^
The Web UI is based on ReactJS + Redux. The Web UI is based on ReactJS + Redux.