summaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
authorRomain Forlot <romain.forlot@iot.bzh>2017-09-19 16:43:41 +0200
committerRomain Forlot <romain.forlot@iot.bzh>2017-12-14 11:00:25 +0100
commite11314b2e9fef34f569bb7b042b432aed661cdc0 (patch)
treeaaaae4d5820238e53a555f290a0a1ea8faa28b9e /docs
parentf4fba8a2744991ff8c5cb8af4a67c7d9456f1057 (diff)
Added documentation
Change-Id: Iaa6bb0470652d3d0dc97c6320dbf210567ccec80 Signed-off-by: Romain Forlot <romain.forlot@iot.bzh>
Diffstat (limited to 'docs')
-rw-r--r--docs/0-Doc-Revisions.md6
-rw-r--r--docs/README.md22
-rw-r--r--docs/SUMMARY.md9
-rw-r--r--docs/_layouts/ebook/page.html36
-rw-r--r--docs/_layouts/ebook/pdf_footer.html13
-rw-r--r--docs/_layouts/ebook/pdf_header.html13
-rw-r--r--docs/_layouts/ebook/summary.html58
-rw-r--r--docs/_layouts/layout.html28
-rw-r--r--docs/cover.jpgbin0 -> 254719 bytes
-rw-r--r--docs/cover_small.jpgbin0 -> 13255 bytes
-rw-r--r--docs/part-1/0_Abstract.md9
-rw-r--r--docs/part-1/1-Architecture.md44
-rw-r--r--docs/part-1/2-Configuration.md75
-rw-r--r--docs/part-1/3-Plugins.md4
-rw-r--r--docs/part-1/4-SignalComposerAPI.md33
-rw-r--r--docs/part-1/pictures/Global_Signaling_Architecture.pngbin0 -> 182698 bytes
-rw-r--r--docs/part-1/pictures/iotbzh_logo_small.pngbin0 -> 6989 bytes
-rw-r--r--docs/resources/cover.svg210
-rw-r--r--docs/resources/ebook.css386
-rwxr-xr-xdocs/resources/make_cover.sh27
20 files changed, 973 insertions, 0 deletions
diff --git a/docs/0-Doc-Revisions.md b/docs/0-Doc-Revisions.md
new file mode 100644
index 0000000..a2ae277
--- /dev/null
+++ b/docs/0-Doc-Revisions.md
@@ -0,0 +1,6 @@
+Document revisions
+==================
+
+| Date | Version | Designation  | Author |
+|-------------|---------|--------------------------------------|-------------------------|
+| 19 Sep 2017 | 4.99-EERC1 | Initial release | R. Forlot [ Iot.bzh ] |
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 0000000..337a14c
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,22 @@
+# Introduction
+
+This template is also a documentation that explains how to setup and write
+your documentation with gitbook.
+
+<br>
+<br>
+<br>
+<br>
+<br>
+
+| *Meta* | *Data* |
+| -- | -- |
+| **Title** | {{ config.title }} |
+| **Author** | {{ config.author }} |
+| **Description** | {{ config.description }} |
+| **Keywords** | {{ config.keywords }} |
+| **Language** | English |
+| **Published** | Published {{ config.published }} as an electronic book |
+| **Updated** | {{ gitbook.time }} |
+| **Collection** | Open-source |
+| **Website** | [{{ config.website }}]({{ config.website }}) |
diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md
new file mode 100644
index 0000000..9d0f0a8
--- /dev/null
+++ b/docs/SUMMARY.md
@@ -0,0 +1,9 @@
+# Summary
+
+* [Document revisions](0-Doc-Revisions.md)
+
+* [Signal Composer](part-1/0_Abstract.md)
+ * [Architecture](part-1/1-Architecture.md)
+ * [Configuration](part-1/2-Configuration.md)
+ * [Plugin](part-1/3-Plugins.md)
+ * [Signal Composer API](part-1/4-SignalComposerAPI.md)
diff --git a/docs/_layouts/ebook/page.html b/docs/_layouts/ebook/page.html
new file mode 100644
index 0000000..bf325e9
--- /dev/null
+++ b/docs/_layouts/ebook/page.html
@@ -0,0 +1,36 @@
+{% extends "layout.html" %}
+
+{% block title %}{{ page.title }}{% endblock %}
+{% block description %}{{ page.description }}{% endblock %}
+
+{% block style %}
+ {### Include theme css before plugins css ###}
+ {% if not fileExists(config.styles.print) %}
+ {% if options.format %}
+ <link rel="stylesheet" href="{{ (options.format + ".css")|resolveAsset }}">
+ {% else %}
+ <link rel="stylesheet" href="{{ "ebook.css"|resolveAsset }}">
+ {% endif %}
+ {% endif %}
+
+ {{ super() }}
+
+ {### Custom stylesheets for the book ###}
+
+ {% for type, style in config.styles %}
+ {% if fileExists(style) and (type == "ebook" or type == "print" or type == options.format) %}
+ <link rel="stylesheet" href="{{ style|resolveFile }}">
+ {% endif %}
+ {% endfor %}
+{% endblock %}
+
+{% block body %}
+<div class="page">
+ {% block page %}
+ <h1 class="book-chapter book-chapter-{{ page.depth }}">{{ page.title }}</h1>
+ <div class="section">
+ {{ page.content|safe }}
+ </div>
+ {% endblock %}
+</div>
+{% endblock %}
diff --git a/docs/_layouts/ebook/pdf_footer.html b/docs/_layouts/ebook/pdf_footer.html
new file mode 100644
index 0000000..679e562
--- /dev/null
+++ b/docs/_layouts/ebook/pdf_footer.html
@@ -0,0 +1,13 @@
+{% extends "./page.html" %}
+{% block body %}
+<div id="pdf-footer" class="pdf-footer">
+ <span class="footer-left">Version {{ config.version }}</span>
+ <span class="footer-right">{{ page.num }}</span>
+ <span class="footer-center">{{ config.published }}</span>
+</div>
+
+<!-- Allow to hide footer for some pages using hidepagefooters config in book.json -->
+<script>
+ if (({% for num in config.hidepagefooters %}{{ page.num }} == {{ num }} || {% endfor %}false)) document.getElementById('pdf-footer').style.display = 'none'
+</script>
+{% endblock %}
diff --git a/docs/_layouts/ebook/pdf_header.html b/docs/_layouts/ebook/pdf_header.html
new file mode 100644
index 0000000..ef49641
--- /dev/null
+++ b/docs/_layouts/ebook/pdf_header.html
@@ -0,0 +1,13 @@
+{% extends "./page.html" %}
+{% block body %}
+<div id="pdf-header" class="pdf-header">
+ <span class="header-left">IoT.Bzh</span>
+ <span class="header-right">{{ config.title }}</span>
+</div>
+
+<!-- Allow to hide header for some pages using hidepageheaders config in book.json -->
+<script>
+ if (({% for num in config.hidepageheaders %}{{ page.num }} == {{ num }} || {% endfor %}false)) document.getElementById('pdf-header').style.display = 'none'
+</script>
+
+{% endblock %} \ No newline at end of file
diff --git a/docs/_layouts/ebook/summary.html b/docs/_layouts/ebook/summary.html
new file mode 100644
index 0000000..be328a4
--- /dev/null
+++ b/docs/_layouts/ebook/summary.html
@@ -0,0 +1,58 @@
+{% extends "./page.html" %}
+
+{% block title %}{{ "SUMMARY"|t }}{% endblock %}
+
+{% macro articles(_articles) %}
+ {% for article in _articles %}
+ <li>
+ <span class="inner">
+ {% if article.path or article.url %}
+ {% if article.path %}
+ <a href="{{ article.path|contentURL }}{{ article.anchor }}">{{ article.title }}</a>
+ {% else %}
+ <a target="_blank" href="{{ article.url }}">{{ article.title }}</a>
+ {% endif %}
+ {% else %}
+ <span>{{ article.title }}</span>
+ {% endif %}
+ {% if 1 %}
+ <span class="page">{{ article.level }}</span>
+ {% endif %}
+ </span>
+ {% if article.articles.length > 0 %}
+ <ol>
+ {{ articles(article.articles) }}
+ </ol>
+ {% endif %}
+ </li>
+ {% endfor %}
+{% endmacro %}
+
+{% block page %}
+<div class="section toc">
+ <h1>{{ "SUMMARY"|t }}</h1>
+ <ol>
+ {% for part in summary.parts %}
+ {% if part.title %}
+ <li class="part-title">
+ <h2>{{ part.title }}</h2>
+ </li>
+ {% endif %}
+ {{ articles(part.articles) }}
+
+ {% if not loop.last %}
+ <li class="divider"></li>
+ {% endif %}
+ {% endfor %}
+
+ {% if glossary.path %}
+ <li>
+ <span class="inner">
+ <a href="{{ ('/' + glossary.path)|contentURL }}">{{ "GLOSSARY"|t }}</a>
+ </span>
+ </li>
+ {% endif %}
+ </ol>
+</div>
+{% endblock %}
+
diff --git a/docs/_layouts/layout.html b/docs/_layouts/layout.html
new file mode 100644
index 0000000..3d5aca6
--- /dev/null
+++ b/docs/_layouts/layout.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html lang="{{ config.language }}" {% if page.dir == "rtl" %}dir="rtl"{% endif %}>
+ <head>
+ <meta charset="UTF-8">
+ <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
+ <title>{% block title %}{{ config.title|d("GitBook", true) }}{% endblock %}</title>
+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+ <meta name="description" content="{% block description %}{% endblock %}">
+ <meta name="generator" content="GitBook {{ gitbook.version }}">
+ {% if config.author %}<meta name="author" content="{{ config.author }}">{% endif %}
+ {% if config.isbn %}<meta name="identifier" content="{{ config.isbn }}" scheme="ISBN">{% endif %}
+ {% block style %}
+ {% for resource in plugins.resources.css %}
+ {% if resource.url %}
+ <link rel="stylesheet" href="{{ resource.url }}">
+ {% else %}
+ <link rel="stylesheet" href="{{ resource.path|resolveAsset }}">
+ {% endif %}
+ {% endfor %}
+ {% endblock %}
+
+ {% block head %}{% endblock %}
+ </head>
+ <body>
+ {% block body %}{% endblock %}
+ {% block javascript %}{% endblock %}
+ </body>
+</html>
diff --git a/docs/cover.jpg b/docs/cover.jpg
new file mode 100644
index 0000000..668f253
--- /dev/null
+++ b/docs/cover.jpg
Binary files differ
diff --git a/docs/cover_small.jpg b/docs/cover_small.jpg
new file mode 100644
index 0000000..216b4bb
--- /dev/null
+++ b/docs/cover_small.jpg
Binary files differ
diff --git a/docs/part-1/0_Abstract.md b/docs/part-1/0_Abstract.md
new file mode 100644
index 0000000..beb610a
--- /dev/null
+++ b/docs/part-1/0_Abstract.md
@@ -0,0 +1,9 @@
+# Signal Composer binding: A high level signal handler
+
+## Abstract
+
+You will find in this documentation a presentation about Signal Composer
+architecture. Signal Composer is an Application Framework binding meant to
+facilitate handling signaling, by compose, divide and create new virtuals
+signals from RAW signals coming from _low level_ binding that handle read/write,
+encode/decode on different protocols that a car could use (CAN, LIN, Ethernet, GPS, i2c, ...).
diff --git a/docs/part-1/1-Architecture.md b/docs/part-1/1-Architecture.md
new file mode 100644
index 0000000..a907882
--- /dev/null
+++ b/docs/part-1/1-Architecture.md
@@ -0,0 +1,44 @@
+# Signal Composer
+
+## Architecture
+
+Here is a quick picture about the signaling architecture :
+
+![GlobalArchitecture]
+
+Key here are on both layer, **low** and **high**.
+
+- **Low level** are in charge of handle a data exchange protocol to decode/encode and retransmit
+ with an AGL compatible format, most convenient way using **Application Framework** event. These are divised in two parts, which are :
+ - Transport Layer plug-in that read/write 1 protocol.
+ - Decoding/Encoding part that expose signals and a way to access them.
+- **High level signal composer** gathers multiple **low level** signaling sources and creates new
+ virtuals signals from the **raw** signals defined (eg. signal made from gps latitude and
+ longitude that calcul the heading of vehicle). It is modular and each signal source should be
+ handled by specific plugins which take care of get the underlying event from **low level** or
+ define signaling composition with simple or complex operation to output value from **raw** signals
+
+There are three main parts with **Signal Composer**:
+
+- Configuration files which could be splitted in differents files. That will define:
+ - metadata with name of **signal composer** api name
+ - additionnals configurations files
+ - plugins used if so, **low level** signals sources
+ - signals definitions
+- Dedicated plugins
+- Signal composer API
+
+## Terminology
+
+Here is a little terminology guide to set the vocabulary:
+
+- **sources**
+- **signals**
+- **api**
+- **event**
+- **callbacks**
+- **action**
+- **virtual signals**
+- **raw signals**
+
+[GlobalArchitecture]: pictures/Global_Signaling_Architecture.png "Global architecture"
diff --git a/docs/part-1/2-Configuration.md b/docs/part-1/2-Configuration.md
new file mode 100644
index 0000000..a68fd62
--- /dev/null
+++ b/docs/part-1/2-Configuration.md
@@ -0,0 +1,75 @@
+# Configuration
+
+Configuration defines all in **Signal composer** each signals and sources has to be defined in it.
+At start, configuration will be searched in default binding configuration directory which should be
+_/var/lib/afm/applications/signal-composer/1.0/etc/_. Binding search for a file name as _init-daemon*.json_. Others files could be used to split sections and don't have 1 big fat definitions file.
+
+Saying that you have 4 sections to define:
+
+- **metadata**: Main parts and the only one that can't be in a separates configuration. This must appears in the main configuration file.
+- **plugins** (optionnal): Declare plugins that will be used by *sources* and *signals* for the subscription and composition.
+- **sources**: Declare **low level** signals sources (eg. low-can, gps, mraa, ...).
+- **signals**: Declare signals, virtuals and raw.
+
+## Metadata
+
+Here we define some metadata about **signal composer** binding. Fields to configure
+are :
+
+- **label**: self-explanatory
+- **version** (optionnal): self-explanatory
+- **api**: name that the binding will be initialized to and later be accessible by **Application Framework**
+- **info** (optionnal): self-explanatory
+- **require** (optionnal): list of required external apis.
+- **files** (optionnal): list of additionnals files. **ONLY NAME** or part of it without extension. These
+ files are loaded to find sections: *plugins*, *sources* and *signals*.
+
+## Plugins
+
+This section is the only which is optionnal, it is needed if you develop specifics C/C++ plugins
+to be used with signal-composer. LUA and API consumption does not need plugins.
+
+Default path to search for a plugin is in the binding library directory in a subdirectory _plugins_
+_/var/lib/afm/applications/signal-composer/1.0/lib/plugins_. Else you could use the environment variable _CONTROL_PLUGIN_PATH_ with a semicolon separated list of
+directory.
+
+Fields are:
+
+- **label**: Define the plugin name. This is that label that will be used on **sources** and
+ **signals** callbacks.
+- **version** (optionnal): self-explanatory
+- **info** (optionnal): self-explanatory
+- **basename**: shared library file name **without** the extension.
+
+## Sources
+
+A source is a **low level** API that will be consume by the **signal composer**
+to be able to expose those signals with additionnals treatments, filtering,
+thinning,... and create new virtuals signals composed with basic raw signals.
+
+A source is defined with following fields:
+
+- **api**: Name of the source API.
+- **info** (optionnal): self-explanatory
+- **init** (optionnal): an **action** to take to initialize a source. May you have to call a verb from that API, of create a files etc.
+- **getSignals** (optionnal); an **action** to take to get signals from that
+ source. These callback will be used for each signals defined later in the **signals** section. Dedicated arguments for each signal could be defined in
+ **signals**.
+
+## Signals
+
+A signal definition could be either a **raw** one or a **virtual** one. A **virtual signal** is a set of existing **raw signals** associated to an **action**
+on reception which will compute the value of the signal.
+
+- **id**: Unique identifier used inside **signal composer**, used to compose virtual signals.
+- **event**: specify a **raw signal** coming from **low level** sources. Couldn't
+ be used with **depends** field, only one of them is possible.
+- **depends**: specify others signals **id** that compose it (eg: heading is
+ composed with longitude+latitude signals.). Couldn't be used with **event** field
+ at same time.
+- **unit** (optionnal): Unit used to exprime the signal
+- **frequency** (optionnal): Frequency maximum at which the signal could be
+ requested or sent. This is a thinning made at **high level** so not best suited for performance. Used **low level** native filtering capabilities when possible.
+- **getSignalsArgs**: a JSON object used at subscription time. Meant to enabled
+ filtering capabilities at subscription and to be able to customize in general a subcription request by signal if needed.
+- **onReceived**: an **action** to take when this signal is received!
diff --git a/docs/part-1/3-Plugins.md b/docs/part-1/3-Plugins.md
new file mode 100644
index 0000000..1cfb580
--- /dev/null
+++ b/docs/part-1/3-Plugins.md
@@ -0,0 +1,4 @@
+# Plugins
+
+Plugins are C/C++ shared library that is loaded by the binding to execute some simple routine. Routine could be on reception of a new signal or at sources
+initialization time or signal subscription with the respective JSON field **onReceived**, **init** and **getSignals**.
diff --git a/docs/part-1/4-SignalComposerAPI.md b/docs/part-1/4-SignalComposerAPI.md
new file mode 100644
index 0000000..6e53800
--- /dev/null
+++ b/docs/part-1/4-SignalComposerAPI.md
@@ -0,0 +1,33 @@
+# Signal Composer API
+
+## get
+
+You can get a signal value be requesting the API with the verb *get*:
+
+```json
+signal-composer get {"signal": "vehicle_speed", "options": {"average": 10}}
+signal-composer get {"signal": "vehicle_speed", "options": {"minimum": 10}}
+signal-composer get {"signal": "vehicle_speed", "options": {"maximum": 10}}
+signal-composer get {"signal": "vehicle_speed"}
+```
+
+You apply apply some simple mathematical function by default present in the binding
+, by default **last** is used:
+
+- **average**: make an average on X latest seconds.
+- **minimum**: return the minimum value found in the X latest seconds.
+- **maximum**: return the maximum value found in the X latest seconds.
+- **last**: return the latest value.
+
+## list
+
+Verb **list** will output the list of defined signals.
+
+## loadConf
+
+Verb **loadConf** let you add new files to be able to add new **sources** or
+**signals**.
+
+```json
+signal-composer loadConf {"filepath": "/path/to/your/json/file.json"}
+```
diff --git a/docs/part-1/pictures/Global_Signaling_Architecture.png b/docs/part-1/pictures/Global_Signaling_Architecture.png
new file mode 100644
index 0000000..7934d3f
--- /dev/null
+++ b/docs/part-1/pictures/Global_Signaling_Architecture.png
Binary files differ
diff --git a/docs/part-1/pictures/iotbzh_logo_small.png b/docs/part-1/pictures/iotbzh_logo_small.png
new file mode 100644
index 0000000..6a98c60
--- /dev/null
+++ b/docs/part-1/pictures/iotbzh_logo_small.png
Binary files differ
diff --git a/docs/resources/cover.svg b/docs/resources/cover.svg
new file mode 100644
index 0000000..6726de7
--- /dev/null
+++ b/docs/resources/cover.svg
@@ -0,0 +1,210 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="1800"
+ height="2360"
+ viewBox="0 0 1800 2360"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="cover.svg">
+ <defs
+ id="defs4175">
+ <filter
+ style="color-interpolation-filters:sRGB"
+ inkscape:label="Drop Shadow"
+ id="filter4000">
+ <feFlood
+ result="flood"
+ flood-color="rgb(0,0,0)"
+ flood-opacity="0.475"
+ id="feFlood4002" />
+ <feComposite
+ result="composite1"
+ operator="in"
+ in="flood"
+ in2="SourceGraphic"
+ id="feComposite4004" />
+ <feGaussianBlur
+ result="blur"
+ stdDeviation="5"
+ id="feGaussianBlur4006" />
+ <feOffset
+ result="offset"
+ dy="8"
+ dx="8"
+ id="feOffset4008" />
+ <feComposite
+ result="composite2"
+ operator="over"
+ in="SourceGraphic"
+ in2="offset"
+ id="feComposite4010" />
+ </filter>
+ <filter
+ style="color-interpolation-filters:sRGB"
+ id="filter4000-6"
+ inkscape:label="Drop Shadow">
+ <feFlood
+ id="feFlood4002-4"
+ flood-opacity="0.475"
+ flood-color="rgb(0,0,0)"
+ result="flood" />
+ <feComposite
+ id="feComposite4004-6"
+ in2="SourceGraphic"
+ in="flood"
+ operator="in"
+ result="composite1" />
+ <feGaussianBlur
+ id="feGaussianBlur4006-2"
+ stdDeviation="5"
+ result="blur" />
+ <feOffset
+ id="feOffset4008-8"
+ dx="8"
+ dy="8"
+ result="offset" />
+ <feComposite
+ id="feComposite4010-9"
+ in2="offset"
+ in="SourceGraphic"
+ operator="over"
+ result="composite2" />
+ </filter>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.24748737"
+ inkscape:cx="928.3577"
+ inkscape:cy="404.58117"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:snap-text-baseline="false"
+ units="px"
+ inkscape:window-width="1920"
+ inkscape:window-height="1171"
+ inkscape:window-x="1920"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ showguides="false" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,1307.6379)">
+ <g
+ id="iotbzh-logo"
+ transform="matrix(2.3917866,0,0,2.3917866,216.6324,-1946.4393)"
+ inkscape:export-filename="/home/sdx/Pictures/Logo/logo_iot_bzh_100dpi.png"
+ inkscape:export-xdpi="100.22011"
+ inkscape:export-ydpi="100.22011"
+ style="display:inline;filter:url(#filter4000-6)">
+ <text
+ sodipodi:linespacing="125%"
+ id="text3557-5-3-7-0-7-3"
+ y="519.50671"
+ x="27.886671"
+ style="font-style:normal;font-weight:normal;font-size:97.09867096px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;display:inline;fill:#000000;fill-opacity:1;stroke:none"
+ xml:space="preserve"><tspan
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:97.09867096px;line-height:125%;font-family:FreeEuro;-inkscape-font-specification:'FreeEuro Bold';text-align:start;writing-mode:lr-tb;text-anchor:start"
+ y="519.50671"
+ x="27.886671"
+ id="tspan3559-5-4-1-5-0-6"
+ sodipodi:role="line">IOT</tspan></text>
+ <path
+ inkscape:connector-curvature="0"
+ d="m 286.73007,473.23356 c 28.21686,16.29102 28.75566,58.73779 0.99693,78.53831 -7.67688,5.47598 -8.77935,4.91028 -1.99529,-1.0238 17.47377,-15.28453 17.98492,-42.17775 1.08522,-57.09786 l -3.91266,-3.45435 0.72312,-3.71053 c 0.39771,-2.04076 0.5997,-5.73115 0.44885,-8.20083 -0.33876,-5.54623 0.15803,-6.49185 2.65383,-5.05094 z m -64.76568,11.40332 c 7.06047,-7.74198 18.64659,-14.16089 29.04027,-16.08874 l 6.87489,-1.27521 0.87404,2.89709 c 0.4807,1.59343 0.67439,5.2245 0.43037,8.06906 l -0.44364,5.17195 -6.13887,1.6918 c -10.91241,3.00731 -20.4022,10.85909 -25.4533,21.05979 l -2.41633,4.87984 -2.74281,-0.41238 c -5.14252,-0.77316 -12.72985,-3.97645 -12.79123,-5.40033 -0.092,-2.13451 8.34659,-15.74625 12.76661,-20.59287 z m 33.20546,36.39493 c -28.21687,16.29101 -65.24624,-4.46574 -68.51461,-38.40577 -0.9039,-9.38637 0.13723,-10.0583 1.88428,-1.21608 4.49989,22.77499 27.53453,36.66428 48.90556,29.48876 l 4.94788,-1.66128 2.85184,2.48149 c 1.56852,1.36481 4.66349,3.38493 6.87772,4.48914 4.97257,2.47973 5.54308,3.38282 3.04733,4.82374 z m 22.50729,-61.79039 c 3.17451,9.98553 2.94038,23.22889 -0.58688,33.19399 l -2.33309,6.59143 -2.94597,-0.69161 c -1.6203,-0.38041 -4.86173,-2.02821 -7.2032,-3.6618 l -4.25721,-2.97018 1.60429,-6.16234 c 2.85178,-10.95404 0.79685,-23.09833 -5.51167,-32.57307 l -3.01788,-4.53253 1.72854,-2.16916 c 3.24083,-4.06698 9.80863,-9.03614 11.07242,-8.37738 1.89457,0.98756 9.46336,15.1015 11.45065,21.35265 z m -48.80223,10.31437 c 0,-32.58201 36.49058,-54.27201 67.51771,-40.1325 8.58077,3.9104 8.6421,5.148 0.11108,2.23988 -21.97368,-7.49048 -45.51946,5.51348 -49.99082,27.6091 l -1.03521,5.11561 -3.57498,1.22902 c -1.96621,0.67596 -5.26316,2.34622 -7.32655,3.71171 -4.63379,3.06649 -5.70115,3.10904 -5.70115,0.22718 z m 42.25842,50.3871 c -10.23499,-2.24356 -21.58699,-9.06801 -28.45341,-17.10525 l -4.5418,-5.31622 2.07194,-2.20549 c 1.13957,-1.21302 4.18733,-3.19628 6.77282,-4.40726 l 4.70085,-2.20176 4.53458,4.47053 c 8.06061,7.94674 19.60535,12.23927 30.96496,11.51329 l 5.43422,-0.34731 1.01427,2.58154 c 1.90169,4.84014 2.92124,13.01261 1.71883,13.77769 -1.80254,1.14695 -17.80995,0.64475 -24.21726,-0.75976 z"
+ style="display:inline;fill:#5a2ca0"
+ id="path3415-4-2-2-5-0-3-7-4-4-1-5" />
+ <text
+ sodipodi:linespacing="125%"
+ id="text3557-5-3-7-46-7-3-7"
+ y="519.50671"
+ x="317.95816"
+ style="font-style:normal;font-weight:normal;font-size:97.09867096px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;display:inline;fill:#000000;fill-opacity:1;stroke:none"
+ xml:space="preserve"><tspan
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:97.09867096px;line-height:125%;font-family:FreeEuro;-inkscape-font-specification:'FreeEuro Bold';text-align:start;writing-mode:lr-tb;text-anchor:start"
+ y="519.50671"
+ x="317.95816"
+ id="tspan3559-5-4-1-90-0-2-9"
+ sodipodi:role="line">BZH</tspan></text>
+ </g>
+ <flowRoot
+ xml:space="preserve"
+ id="root-title"
+ transform="matrix(2.3469382,0,0,2.3469382,464.13874,-1200)"><flowRegion
+ id="flowRegion4303"><rect
+ id="rect4305"
+ width="679.99994"
+ height="141.42853"
+ x="-154.28572"
+ y="400"/>
+ </flowRegion>
+ <flowPara
+ id="title"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:87.5px;line-height:125%;font-family:Verdana;-inkscape-font-specification:'Verdana, Bold';text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1">{title}</flowPara></flowRoot> <flowRoot
+ xml:space="preserve"
+ id="root-subtitle"
+ transform="matrix(1.8523279,0,0,1.8523279,553.97647,-380)"><flowRegion
+ id="flowRegion4303-6"><rect
+ id="rect4305-0"
+ width="852.32806"
+ height="154.51677"
+ x="-239.3591"
+ y="290"/>
+ </flowRegion>
+ <flowPara
+ id="subtitle"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:62.5px;line-height:125%;font-family:Verdana;-inkscape-font-specification:'Verdana, Bold';text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1">{subtitle}</flowPara>
+ </flowRoot>
+ <flowRoot
+ id="root-version"
+ xml:space="preserve"
+ transform="translate(-2.0185547,164)"><flowRegion
+ id="flowRegion4169"><rect
+ y="501.68909"
+ x="343.32947"
+ height="99.591171"
+ width="1117.3768"
+ id="rect4171" /></flowRegion><flowPara
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:50px;line-height:125%;font-family:Verdana;-inkscape-font-specification:'Verdana, Bold';text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1"
+ id="version">{version}</flowPara></flowRoot> <flowRoot
+ transform="translate(-2.0185547,238)"
+ xml:space="preserve"
+ id="root-date"><flowRegion
+ id="flowRegion4170"><rect
+ id="rect4172"
+ width="1117.3768"
+ height="99.591171"
+ x="343.32947"
+ y="501.68909" /></flowRegion><flowPara
+ id="date"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:50px;line-height:125%;font-family:Verdana;-inkscape-font-specification:'Verdana, Bold';text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1">{date}</flowPara></flowRoot> </g>
+</svg>
diff --git a/docs/resources/ebook.css b/docs/resources/ebook.css
new file mode 100644
index 0000000..39f126c
--- /dev/null
+++ b/docs/resources/ebook.css
@@ -0,0 +1,386 @@
+/* IoT.Bzh theaming */
+
+h1 {
+ color: #330066;
+ border-bottom: 2px solid #330066;
+}
+
+h2 {
+ color: #330066;
+}
+
+h3 {
+ color: #330066;
+}
+
+h4 {
+ color: #330066;
+}
+
+
+/* GENERAL ELEMENTS */
+
+/* clear both */
+
+.clear {
+ clear: both;
+}
+
+.section> :last-child {
+ margin-bottom: 0 !important;
+}
+
+.section> :first-child {
+ margin-top: 0 !important;
+}
+
+
+/* SPECIAL ELEMENTS */
+
+
+/* page break always after element on pdf/print definition */
+
+div.pagebreak {
+ page-break-after: always;
+}
+
+
+/* no page break inside element on pdf/print definition */
+
+div.nopb {
+ page-break-inside: avoid !important;
+ margin: 4px 0 4px 0;
+}
+
+
+/* note blocks */
+
+div.note {
+ background: #FCF8E3 none repeat scroll 0% 0%;
+ color: #8A6D3B;
+ padding: 15px;
+ margin-bottom: 10px;
+ border-bottom: 5px solid #DDD;
+ border-color: #FAEBCC;
+ page-break-inside: avoid;
+}
+
+div.note p {
+ padding-bottom: 0;
+ margin-bottom: 0;
+}
+
+
+/* images, figures and captions */
+
+p img {
+ /* center all images */
+ display: block;
+ margin: 0 auto;
+ padding: 10px 0;
+}
+
+figure {
+ margin: 1.0em 0px;
+ padding: 10px 0;
+ text-align: center;
+ page-break-inside: avoid;
+ display: block;
+}
+
+figure img {
+ display: block;
+ margin: 0 auto;
+}
+
+figcaption {
+ clear: left;
+ margin: 1.0em 0 0 0;
+ text-align: center;
+ font-style: italic;
+ line-height: 1.5em;
+ font-size: 80%;
+ color: #666;
+ display: block;
+}
+
+.page .section p img {
+ margin-top: 10px;
+}
+
+
+/* ul, ol list margin fix */
+
+.page .section ol,
+.page .section ul {
+ margin-bottom: 10px;
+}
+
+
+/* blockquotes */
+
+.page .section blockquote {
+ margin: 0 0 0 5%;
+ font-style: italic;
+}
+
+
+/* PAGE SPECIFIC */
+
+
+/* set summary page to right side of the paper */
+
+.page .toc h1 {
+ page-break-before: right;
+}
+
+.page .section.toc {
+ page-break-inside: always;
+}
+
+/* table headers */
+
+div#README\.md table {
+ margin-top: 30px;
+ font-size: 95%;
+}
+
+div#README\.md table thead {
+ display: none;
+}
+
+
+
+/* CITATION AND IMAGES */
+
+
+/* math image styles */
+
+.page .section p img.svg,
+.page .section p img.png {
+ margin-top: 0px;
+ margin-bottom: -2px;
+}
+
+.page .section p img.math {
+ vertical-align: middle;
+ height: auto;
+ width: auto;
+ margin-top: -4px;
+ max-height: 15px;
+}
+
+.page .section p img.math.line1 {
+ margin-top: -7px;
+ max-height: 19px;
+}
+
+.page .section p img.math.line2 {
+ margin-top: -1px;
+ max-height: 30px;
+}
+
+
+/* credits page */
+
+.page .section ul.pictures {
+ margin-left: -30px;
+}
+
+.page .section ul.pictures li {
+ list-style: outside none none;
+}
+
+.page .section ul.pictures li a {
+ float: left;
+}
+
+.page .section ul.pictures li span {
+ display: block;
+ margin-left: 100px;
+}
+
+
+
+/* sub and super script */
+
+.page .section sub {
+ font-size: 80%;
+ margin-left: 1px;
+}
+
+
+/* citations and references */
+
+.page .section sup {
+ margin-left: -1px;
+ margin-right: 2px;
+ font-size: 80%;
+}
+
+.page .section sup:before {
+ content: " ";
+}
+
+.page .section ul.citations,
+.page .section ul.references {
+ margin-left: -30px;
+}
+
+
+.page .section ul.citations li:nth-child(1) {
+ margin-top: 20px;
+ padding-top: 20px;
+ border-top: 1px solid #BBB;
+}
+
+.page .section ul.citations li,
+.page .section ul.references li {
+ list-style: outside none none;
+}
+
+.page .section ul.citations li {
+ font-size: 80%;
+}
+
+.page .section ul.citations li>span:nth-child(1),
+.page .section ul.references li>span:nth-child(1) {
+ display: block;
+ float: left;
+ text-align: left;
+ width: 70px
+}
+
+.page .section ul.citations li>span:nth-child(1) {
+ width: 50px
+}
+
+.page .section ul.references li div {
+ margin-left: 70px;
+}
+
+.page .section ul.citations li div {
+ margin-left: 50px;
+}
+
+.page .section a[href="#"],
+.page .section a[href="#"]:link,
+.page .section a[href="#"]:visited,
+.page .section a[href="#"]:hover,
+.page .section a[href="#"]:focus {
+ text-decoration: none;
+ color: inherit;
+ cursor: text;
+ font-style: italic;
+}
+
+
+/* self referential footnotes */
+
+.page .section div[type="selfref"] a[href="#"],
+.page .section div[type="selfref"] a[href="#"]:link,
+.page .section div[type="selfref"] a[href="#"]:visited,
+.page .section div[type="selfref"] a[href="#"]:hover,
+.page .section div[type="selfref"] a[href="#"]:focus {
+ font-style: normal;
+}
+
+.page .section div[type="selfref"] span:nth-child(1) {
+ display: none;
+}
+
+
+/* page break always after element on pdf/print definition */
+
+div.page-break {
+ page-break-inside: always;
+}
+
+div.page-break:before {
+ content: ' ';
+}
+
+
+/* no page break inside element on pdf/print definition */
+
+div.nopb {
+ page-break-inside: avoid;
+}
+
+/* justify text */
+p {
+ text-align: justify;
+}
+
+/* page header and footer */
+
+.pdf-footer,
+.pdf-header {
+ margin-top: 20px;
+ color: #aaa;
+}
+
+.pdf-header .header-left {
+ float: left;
+ margin-left: 2em;
+ margin-right: auto;
+}
+
+.pdf-header .header-right {
+ display: table;
+ margin-left: auto;
+ margin-right: 2em;
+}
+
+.pdf-footer .sub {
+ padding-top: 8px;
+ font-size: 70%;
+}
+
+.pdf-header .sub {
+ padding-top: 2px;
+ font-size: 70%;
+}
+
+.pdf-footer {
+ padding-top: 10px;
+ border-top: 1px solid #eee;
+}
+
+.pdf-footer .footer-left {
+ float: left;
+ margin-left: 2em;
+ margin-right: auto;
+}
+
+.pdf-footer .footer-center {
+ display: table;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+.pdf-footer .footer-right {
+ float: right;
+ margin-left: auto;
+ margin-right: 2em;
+}
+
+.pdf-header {
+ padding-bottom: 10px;
+ border-bottom: 1px solid #eee;
+}
+
+.pdf-header .header-pages-count {
+ float: right;
+ text-align: right;
+}
+
+.pdf-header .header-pages-count a,
+.pdf-header .header-pages-count a:visited,
+.pdf-header .header-pages-count a:active,
+.pdf-header .header-pages-count a:focus,
+.pdf-header .header-pages-count a:link {
+ text-decoration: none;
+ color: #aaa;
+ cursor: text;
+}
diff --git a/docs/resources/make_cover.sh b/docs/resources/make_cover.sh
new file mode 100755
index 0000000..1026ecb
--- /dev/null
+++ b/docs/resources/make_cover.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+DOCS_DIR=$(cd $(dirname $0)/.. && pwd)
+BOOKFILE=$DOCS_DIR/../book.json
+
+TITLE=$(grep '"title":' $BOOKFILE | cut -d'"' -f 4)
+SUBTITLE=$(grep '"subtitle":' $BOOKFILE | cut -d'"' -f 4)
+VERSION="Version $(grep '"version":' $BOOKFILE | cut -d'"' -f 4)"
+DATE=$(grep '"published":' $BOOKFILE | cut -d'"' -f 4)
+
+[ -z "$TITLE" ] && { echo "Error TITLE not set!" ; exit 1; }
+[ -z "$VERSION" ] && { echo "Error VERSION not set!" ; exit 1; }
+[ -z "$DATE" ] && { echo "Error DATE not set!" ; exit 1; }
+
+
+cat $(dirname $0)/cover.svg | sed -e "s/{title}/$TITLE/g" \
+ -e "s/font-size:87.5px/font-size:54px/g" \
+ -e "s/{subtitle}/$SUBTITLE/g" \
+ -e "s/font-size:62.5px/font-size:40px/g" \
+ -e "s/{version}/$VERSION/g" \
+ -e "s/{date}/$DATE/g" \
+ > /tmp/cover.svg
+
+# use imagemagick convert tool (cover size must be 1800x2360)
+convert -resize "1600x2160!" -border 100 -bordercolor white -background white \
+ -flatten -quality 100 /tmp/cover.svg $DOCS_DIR/cover.jpg
+
+convert -resize "200x262!" $DOCS_DIR/cover.jpg $DOCS_DIR/cover_small.jpg