diff --git a/apps/dashboard/xaal/dashboard/app.py b/apps/dashboard/xaal/dashboard/app.py
index 1944d25cd573535e2bc2690e4284de9a1a3dacbf..bb797b97c659d67fcae5be3d519ff899e00caf29 100644
--- a/apps/dashboard/xaal/dashboard/app.py
+++ b/apps/dashboard/xaal/dashboard/app.py
@@ -8,7 +8,7 @@ from gevent.pywsgi import WSGIServer
 from geventwebsocket.handler import WebSocketHandler
 
 
-from .pages import default_pages
+from .pages import default_pages,warp10
 from .core import xaal_core
 from .core import sio 
 
@@ -32,6 +32,7 @@ def run():
     TEMPLATE_PATH.append(root)
 
     xaal_core.setup()
+    warp10.setup()
     # debug disable template cache & enable error reporting
     debug(True)
     bottle_app = default_app()
diff --git a/apps/dashboard/xaal/dashboard/core/xaal_core.py b/apps/dashboard/xaal/dashboard/core/xaal_core.py
index 7068b42bd71af53c76ed8a6ff50e5101493bb81f..9ed852e1d988552715f17142894a05be85bd42a4 100644
--- a/apps/dashboard/xaal/dashboard/core/xaal_core.py
+++ b/apps/dashboard/xaal/dashboard/core/xaal_core.py
@@ -33,8 +33,8 @@ def event_handler(ev_type,dev):
     
 def setup():
     """ setup xAAL Engine & Device. And start it in a Greenlet"""
-    helpers.setup_console_logger()
     global monitor 
+    helpers.setup_console_logger()
     engine = Engine()
     cfg = tools.load_cfg(PACKAGE_NAME)
     if not cfg:
diff --git a/apps/dashboard/xaal/dashboard/pages/base.py b/apps/dashboard/xaal/dashboard/pages/base.py
index 020d61f7fb6a2c161723937bdc1bab1192e0b5f7..caaef6938b8219abb627e571d31c6dce76c0de33 100644
--- a/apps/dashboard/xaal/dashboard/pages/base.py
+++ b/apps/dashboard/xaal/dashboard/pages/base.py
@@ -85,8 +85,6 @@ def save_metadata(addr):
 
 
 
-
-
 @route('/grid')
 @view('grid.mako')
 def test_grid():
@@ -102,3 +100,4 @@ def socketio_latency_test():
 @view('links.mako')
 def links():
     return {'title':'Links'}
+
diff --git a/apps/dashboard/xaal/dashboard/pages/warp10.py b/apps/dashboard/xaal/dashboard/pages/warp10.py
new file mode 100644
index 0000000000000000000000000000000000000000..358e14c78b4e2ba968e1de878c9dcb96376dd934
--- /dev/null
+++ b/apps/dashboard/xaal/dashboard/pages/warp10.py
@@ -0,0 +1,80 @@
+from xaal.lib import tools
+from .default import view,route
+from .default import xaal_core as xaal
+
+
+from bottle import get,response
+import logging
+import ujson
+import requests
+
+TOKEN=None
+URL=None
+CLASS = None
+
+
+DAILY_REQ = """ [ $TOKEN '%s' { 'devid' '%s'  } NOW 49 h ] FETCH """
+
+bindings = {'thermometer.basic' : 'temperature',
+            'barometer.basic'   : 'pressure',
+            'hygrometer.basic'  : 'humidity',
+            'powermeter.basic'  : 'power',
+            'co2meter.basic'  : 'co2',
+            }
+
+logger = logging.getLogger(__name__)
+
+def setup():
+    global TOKEN,URL,CLASS
+    cfg = tools.load_cfg(xaal.PACKAGE_NAME).get('config',None)
+    if cfg:
+        TOKEN = cfg.get('warp10_token',None)
+        URL = cfg.get('warp10_url',None)
+        CLASS = cfg.get('warp10_class',None)
+        logger.warning("%s %s" % (URL,CLASS))
+
+def init_req():
+    return """'%s' 'TOKEN' STORE\n""" % (TOKEN)
+
+
+def query(req):
+    r = requests.post(URL,req)
+    print(r)
+    return r.text
+    
+
+def to_chartjs(data):
+    r = []
+    for tuple_ in data:
+        date = round(tuple_[0] / 1000)
+        value = tuple_[1]
+        #r.append({"x": date, "y":value })
+        r.append((date,value))
+    return r
+
+@get('/warp10/daily/<addr>')
+def daily(addr):
+    global CLASS
+    response.headers['Content-Type'] = 'application/json'
+    res = {}
+    dev=xaal.monitor.devices.get_with_addr(addr)
+    if dev:
+        req = init_req()
+        devtype = dev.devtype
+        var = bindings.get(devtype,None)
+        if not var:
+            return '{}'
+        class_ = '%s.%s.%s' % (CLASS,devtype,var)
+        tmp = DAILY_REQ % (class_,addr)
+        req = init_req() + tmp
+        data=query(req)
+        
+        res = ujson.loads(data)[0][0]['v']
+    return ujson.dumps(to_chartjs(res))
+
+
+@route('/warp10/graph/<addr>')
+@view('graph.mako')
+def graph(addr):
+    r = {"title" : "Warp10 daily","addr":addr}
+    return r
diff --git a/apps/dashboard/xaal/dashboard/static/css/btns.css b/apps/dashboard/xaal/dashboard/static/css/btns.css
new file mode 100644
index 0000000000000000000000000000000000000000..2b14630f807b5abc703d427588d3969f62e89fd3
--- /dev/null
+++ b/apps/dashboard/xaal/dashboard/static/css/btns.css
@@ -0,0 +1,45 @@
+.onoffswitch {
+    position: relative; width: 60px;
+    -webkit-user-select:none; -moz-user-select:none; -ms-user-select: none;
+}
+.onoffswitch-checkbox {
+    display: none;
+}
+.onoffswitch-label {
+    display: block; overflow: hidden; cursor: pointer;
+    border: 1px solid #999999; border-radius: 20px;
+}
+.onoffswitch-inner {
+    display: block; width: 200%; margin-left: -100%;
+    transition: margin 0.1s ease-in 0s;
+}
+.onoffswitch-inner:before, .onoffswitch-inner:after {
+    display: block; float: left; width: 50%; height: 20px; padding: 0; line-height: 20px;
+    font-size: 14px; color: white; font-family: Trebuchet, Arial, sans-serif; font-weight: bold;
+    box-sizing: border-box;
+}
+.onoffswitch-inner:before {
+    content: "";
+    padding-left: 10px;
+    background-color: #ED054E; color: #FFFFFF;
+}
+.onoffswitch-inner:after {
+    content: "";
+    padding-right: 10px;
+    background-color: #00bbd7; color: #DEDEDE;
+    text-align: right;
+}
+.onoffswitch-switch {
+    display: block; width: 16px; margin: 2px;
+    background: #FFFFFF;
+    position: absolute; top: 0; bottom: 0;
+    right: 36px;
+    border: 1px solid #999999; border-radius: 20px;
+    transition: all 0.1s ease-in 0s; 
+}
+.onoffswitch-checkbox:checked + .onoffswitch-label .onoffswitch-inner {
+    margin-left: 0;
+}
+.onoffswitch-checkbox:checked + .onoffswitch-label .onoffswitch-switch {
+    right: 0px; 
+}
diff --git a/apps/dashboard/xaal/dashboard/static/css/site.css b/apps/dashboard/xaal/dashboard/static/css/site.css
index 19366f587575e29a35a3bdbf79f6c2d7eb634e5d..91c27fc533ebbde8121ae2df2dd8733e8266ca9c 100644
--- a/apps/dashboard/xaal/dashboard/static/css/site.css
+++ b/apps/dashboard/xaal/dashboard/static/css/site.css
@@ -152,8 +152,8 @@ ul.menu li a:hover {
 }
 
 .grid-background {
-    /*background-image: url("https://wallpaperscraft.com/image/spruce_shadow_dark_background_branch_68089_1920x1200.jpg");*/
-    background-image: url("/static/imgs/bg1.jpg");
+    /* background-image: url("https://wallpaperscraft.com/image/spruce_shadow_dark_background_branch_68089_1920x1200.jpg"); */
+    background-image: url("/static/imgs/bg3.jpg");
     min-height: 900px;
     padding: 0.5em;
 }
@@ -164,7 +164,7 @@ ul.menu li a:hover {
 	border-radius: 3px;
 	padding: 8px;
 	font-size: 120%;
-    height: 200px;
+    height: 250px;
     border: 1px solid var(--color2);
 
     /* display: flex; */
diff --git a/apps/dashboard/xaal/dashboard/static/imgs/bg3.jpg b/apps/dashboard/xaal/dashboard/static/imgs/bg3.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..d68260900bcfda53c3fea335b020aa841217adf6
Binary files /dev/null and b/apps/dashboard/xaal/dashboard/static/imgs/bg3.jpg differ
diff --git a/apps/dashboard/xaal/dashboard/static/imgs/bg5.jpg b/apps/dashboard/xaal/dashboard/static/imgs/bg5.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..d68260900bcfda53c3fea335b020aa841217adf6
Binary files /dev/null and b/apps/dashboard/xaal/dashboard/static/imgs/bg5.jpg differ
diff --git a/apps/dashboard/xaal/dashboard/static/js/site.js b/apps/dashboard/xaal/dashboard/static/js/site.js
index e421ad5bc90fe0886b69f1b1bfb705c1733ffaa9..ce71c031c7de319c9595b62e99aeb682f1dd5789 100644
--- a/apps/dashboard/xaal/dashboard/static/js/site.js
+++ b/apps/dashboard/xaal/dashboard/static/js/site.js
@@ -113,7 +113,8 @@ function run_sio() {
     });
 }
 
-
+//================ refresh attributes  =======================================
+// the old refresh_attributes blocks the page rendering process.
 function sio_refresh_attributes_old() {
     console.log('refresh_attributes');
     var addrs = [];
diff --git a/apps/dashboard/xaal/dashboard/static/manifest.json b/apps/dashboard/xaal/dashboard/static/manifest.json
index ad4812e507972d545d86c727d57df3f928bd63e2..3f3098ccbb8ff5ac62c780d7c417a7b4c3bcdda2 100644
--- a/apps/dashboard/xaal/dashboard/static/manifest.json
+++ b/apps/dashboard/xaal/dashboard/static/manifest.json
@@ -3,10 +3,10 @@
     "name": "xAAL SocketIO DashBoard",
     "background_color": "#fff",
     "display": "standalone",
-    "start_url": "/",
+    "start_url": "../",
     "icons": [
         {
-            "src": "/static/imgs/launcher-icon-4x.png",
+            "src": "./imgs/launcher-icon-4x.png",
             "type": "image/png",
             "sizes": "192x192"
         }
diff --git a/apps/dashboard/xaal/dashboard/static/tags/barometer.tag b/apps/dashboard/xaal/dashboard/static/tags/barometer.tag
new file mode 100644
index 0000000000000000000000000000000000000000..25ba7249202ee7c286e5071ad6e7bcfee304bef5
--- /dev/null
+++ b/apps/dashboard/xaal/dashboard/static/tags/barometer.tag
@@ -0,0 +1,25 @@
+<barometer>
+
+<span class="barometer">
+  <span class="pressure">{ pressure }&nbsp;hPa</span><br/>
+</span>
+
+
+<script>
+  this.addr = opts.xaal_addr;
+  this.pressure = null;
+  receive(data) {
+    this.pressure = Math.round(data['attributes']['pressure']);
+    this.update();
+  }
+</script>
+
+<style>
+.barometer {
+    font-weight: bold;
+    color : var(--color1);
+    align: center;
+}
+</style>
+
+</barometer>
diff --git a/apps/dashboard/xaal/dashboard/static/tags/co2meter.tag b/apps/dashboard/xaal/dashboard/static/tags/co2meter.tag
new file mode 100644
index 0000000000000000000000000000000000000000..5318d6839f8c4eef73633eaef83c440fbb2d0a0f
--- /dev/null
+++ b/apps/dashboard/xaal/dashboard/static/tags/co2meter.tag
@@ -0,0 +1,25 @@
+<co2meter>
+
+<span class="co2meter">
+  <span if={value} class="co2">{ value }&nbsp;ppm</span>
+</span>
+
+
+<script>
+  this.addr = opts.xaal_addr;
+  this.value = '';
+  receive(data) {
+    this.value = data['attributes']['co2'];
+    this.update();
+  }
+</script>
+
+<style>
+.co2 {
+    font-weight: bold;
+    color : var(--color1);
+    align: center;
+}
+</style>
+
+</co2meter>
diff --git a/apps/dashboard/xaal/dashboard/static/tags/door.tag b/apps/dashboard/xaal/dashboard/static/tags/door.tag
new file mode 100644
index 0000000000000000000000000000000000000000..229ccf69f0807772e14e9527526ca0da73a8de22
--- /dev/null
+++ b/apps/dashboard/xaal/dashboard/static/tags/door.tag
@@ -0,0 +1,39 @@
+<door>
+
+<span class="door">
+  <span class="{class}">⚛</span>
+</span>
+
+
+<script>
+  this.addr = opts.xaal_addr;
+  this.class = 'close';
+    
+  receive(data) {
+    state = data['attributes']['position'];
+    if (state == true) {
+       this.class = 'open'
+    }
+    else {
+        this.class = 'close'
+    }
+    this.update();
+  }
+</script>
+
+<style>
+.open {
+    font-weight: bold;
+    color : var(--color3);
+    align: center;
+}
+
+.close {
+    font-weight: bold;
+    color : var(--color2);
+    align: center;
+}
+    
+</style>
+
+</door>
diff --git a/apps/dashboard/xaal/dashboard/static/tags/hygrometer.tag b/apps/dashboard/xaal/dashboard/static/tags/hygrometer.tag
index abc3a4725d3c389aedf614315f9c1064164f663e..bd099460a60532b8e3ecb24a89e776019eb15069 100644
--- a/apps/dashboard/xaal/dashboard/static/tags/hygrometer.tag
+++ b/apps/dashboard/xaal/dashboard/static/tags/hygrometer.tag
@@ -1,15 +1,15 @@
 <hygrometer>
 
 <span class="hygrometer">
-  <span class="humidity">{ humidity }&nbsp;%</span>
+  <span if={value} class="humidity">{ value }&nbsp;%</span>
 </span>
 
 
 <script>
   this.addr = opts.xaal_addr;
-  this.humidity = '__';
+  this.value = null;
   receive(data) {
-    this.humidity = data['attributes']['humidity'];
+    this.value = data['attributes']['humidity'];
     this.update();
   }
 </script>
diff --git a/apps/dashboard/xaal/dashboard/static/tags/lamp.tag b/apps/dashboard/xaal/dashboard/static/tags/lamp.tag
index 775960434f84e5bfa57d0034dd66710feafe3f03..0d7bec2a4a2988c444e532c9a47c0ba38f2d6205 100644
--- a/apps/dashboard/xaal/dashboard/static/tags/lamp.tag
+++ b/apps/dashboard/xaal/dashboard/static/tags/lamp.tag
@@ -1,48 +1,33 @@
 <lamp>
 
-<div class="lamp">
-<div class="{stateClass}">{ light }</div>
-  <button class="button ripple" name="btn_on" onclick={ btn }>ON</button>
-  <button class="button ripple" name="btn_off" onclick={ btn }>OFF</button>
+<div class="onoffswitch">
+  <input type="checkbox" class="onoffswitch-checkbox" id={ tag_id } onchange={ chk } checked={checked}>
+    <label class="onoffswitch-label" for={ tag_id }>
+        <span class="onoffswitch-inner"></span>
+        <span class="onoffswitch-switch"></span>
+    </label>
 </div>
 
 <script>
   this.addr = opts.xaal_addr
-  this.light = '__';
-  this.stateClass = 'state-unknow';
-
+  this.tag_id = 'btn_'+Math.random();
+    
   receive(data) {
-  state = data['attributes']['light']
+    state = data['attributes']['light']
     if (state == true) {
-      this.light = 'ON'
-      this.stateClass = 'state-on'
+      this.checked = true
     }
     else {
-      this.light = 'OFF'
-      this.stateClass = 'state-off'
+      this.checked = false
     }
     this.update()
- }
+  }
 
-  btn(e) {
-    if (e.target.name =='btn_on')
+  chk(e) {
+    if (e.target.checked == true)
       sio_send_request(this.addr,'on',{})
-    if (e.target.name =='btn_off')
+    else
       sio_send_request(this.addr,'off',{})
   }
 </script>
-
-<style>
- .state-on {
-     color:  var(--color3);
-     font-weight: bold;
-     padding: 8px;
- }
-
- .state-unknow, .state-off {
-     color:  var(--color1);
-     font-weight: bold;
-     padding: 8px;
- }
-</style>
 </lamp>
diff --git a/apps/dashboard/xaal/dashboard/static/tags/motion.tag b/apps/dashboard/xaal/dashboard/static/tags/motion.tag
new file mode 100644
index 0000000000000000000000000000000000000000..c4d90c1a8ff91f2617e326dfcb72860147301ef6
--- /dev/null
+++ b/apps/dashboard/xaal/dashboard/static/tags/motion.tag
@@ -0,0 +1,42 @@
+<motion>
+
+<span class="motion">
+  <span class="{class}">⚛</span>
+</span>
+
+
+<script>
+  this.addr = opts.xaal_addr;
+  this.presence = false;
+  this.class = 'no_motion';
+    
+  receive(data) {
+    state = data['attributes']['presence'];
+    if (state == true) {
+       this.presence = true
+       this.class = 'motion'
+    }
+    else {
+       this.presence = false
+        this.class = 'no_motion'
+    }
+    this.update();
+  }
+</script>
+
+<style>
+.motion {
+    font-weight: bold;
+    color : var(--color3);
+    align: center;
+}
+
+.no_motion {
+    font-weight: bold;
+    color : var(--color2);
+    align: center;
+}
+    
+</style>
+
+</motion>
diff --git a/apps/dashboard/xaal/dashboard/static/tags/powermeter.tag b/apps/dashboard/xaal/dashboard/static/tags/powermeter.tag
index 8cb5c6a4a69876dbf61f0a471fd084f735061059..90978f9786d467908f2145e9e6803f4fb9b08c43 100644
--- a/apps/dashboard/xaal/dashboard/static/tags/powermeter.tag
+++ b/apps/dashboard/xaal/dashboard/static/tags/powermeter.tag
@@ -1,7 +1,7 @@
 <powermeter>
 
 <span class="powermeter">
-  <span if={power} class="power">{ power }&nbsp;W</span><br/>
+  <span class="power">{ power }&nbsp;W</span><br/>
   <span if={energy} class="energy">{ energy }&nbsp;kW</span>
 </span>
 
diff --git a/apps/dashboard/xaal/dashboard/static/tags/powerrelay.tag b/apps/dashboard/xaal/dashboard/static/tags/powerrelay.tag
index 1efb80c84d4d561d165472c1b39be0c085cd5dae..8b8ce9a13d64ef864bdc9bf25cc3a71519dd1dda 100644
--- a/apps/dashboard/xaal/dashboard/static/tags/powerrelay.tag
+++ b/apps/dashboard/xaal/dashboard/static/tags/powerrelay.tag
@@ -1,52 +1,40 @@
 <powerrelay>
 
-<div class="powerrelay">
-<div class="{stateClass}">{ power }</div>
-  <button class="button ripple" name="btn_on" onclick={ btn }>ON</button>
-  <button class="button ripple" name="btn_off" onclick={ btn }>OFF</button>
+<div class="onoffswitch">
+  <input type="checkbox" class="onoffswitch-checkbox" id={ tag_id } onchange={ chk } checked={checked}>
+    <label class="onoffswitch-label" for={ tag_id }>
+        <span class="onoffswitch-inner"></span>
+        <span class="onoffswitch-switch"></span>
+    </label>
 </div>
 
 <script>
   this.addr = opts.xaal_addr
-  this.power = '__';
-  this.stateClass = 'state-unknow';
-
+  this.tag_id = 'btn_'+Math.random();
+    
   receive(data) {
     state = data['attributes']['power']
     if (state == true) {
-      this.power = 'ON'
-      this.stateClass = 'state-on'
+      this.checked = true
     }
     else {
-      this.power = 'OFF'
-      this.stateClass = 'state-off'
+      this.checked = false
     }
     this.update()
  }
 
-  btn(e) {
-    if (e.target.name =='btn_on')
+  chk(e) {
+    if (e.target.checked == true)
       sio_send_request(this.addr,'on',{})
-    if (e.target.name =='btn_off')
+    else
       sio_send_request(this.addr,'off',{})
   }
+    
 </script>
 
 <style>
  .powerrelay {
  }
 
- .state-on {
-     color:  var(--color3);
-     font-weight: bold;
-     padding: 8px;
- }
-
- .state-unknow, .state-off {
-     color:  var(--color1);
-     font-weight: bold;
-     padding: 8px;
- }
-
 </style>
 </powerrelay>
diff --git a/apps/dashboard/xaal/dashboard/static/tags/thermometer.tag b/apps/dashboard/xaal/dashboard/static/tags/thermometer.tag
index 7785a06013fe7e2724a5e6b202a88658d877ebb5..e22d204004ea07026b403eb95480743d13ca8f73 100644
--- a/apps/dashboard/xaal/dashboard/static/tags/thermometer.tag
+++ b/apps/dashboard/xaal/dashboard/static/tags/thermometer.tag
@@ -1,14 +1,14 @@
 <thermometer>
 
 <span class="thermometer">
-    <span class="temperature">{ temperature }&nbsp;°</span>
+    <span if={value} class="temperature">{ value }&nbsp;°</span>
 </span>
 
 <script>
   this.addr = opts.xaal_addr
-  this.temperature = '__._';
+  this.value = null
   receive(data) {
-    this.temperature = data['attributes']['temperature']
+    this.value = data['attributes']['temperature']
     this.update()
   }
 </script>
diff --git a/apps/dashboard/xaal/dashboard/templates/base.mako b/apps/dashboard/xaal/dashboard/templates/base.mako
index 30cae818db1e5d1254767ff46a14dd172276337a..b8a44fc027cc064170a059a91bc549b13fbbde8c 100644
--- a/apps/dashboard/xaal/dashboard/templates/base.mako
+++ b/apps/dashboard/xaal/dashboard/templates/base.mako
@@ -11,6 +11,7 @@
   <meta name="mobile-web-app-capable" content="yes">
   <link rel="manifest" href="/static/manifest.json">
   <link rel="icon" href="/static/imgs/favicon.ico">
+  <meta name="theme-color" content="#333" />
 
   <!-- CSS & Fonts -->
   <link href="/static/css/site.css" rel="stylesheet">
@@ -21,16 +22,7 @@
 
   <!-- Menu -->
   <div>
-  <ul class="menu">
-    <li><a href="#" onclick="openNav()">&#9776;</a></li>
-    <li><a href="/devices">Devices</a></li>
-    <li class="active"><a href="/grid">Grid</a></li>
-    <!-- 
-    <li><a href="/bottle_info">HTTPD</a></li>    
-    <li><a href="/links">Links</a></li>
-    <li><a href="/stats">Stats</a></li>
-   -->
-  </ul>
+      <%include file="./menu.mako" />
   </div>
 
 
diff --git a/apps/dashboard/xaal/dashboard/templates/devices.mako b/apps/dashboard/xaal/dashboard/templates/devices.mako
index 3c1fb1f2d26e04775cd5a2b045fd9f9826423489..77202645275a319a360a3f3d3b1ce7f7c3d9fc66 100644
--- a/apps/dashboard/xaal/dashboard/templates/devices.mako
+++ b/apps/dashboard/xaal/dashboard/templates/devices.mako
@@ -1,6 +1,6 @@
 <%inherit file="base.mako"/>
 
-<script src="/static/js/sorttable.js"></script>
+<script src="../static/js/sorttable.js"></script>
 
 
 <!-- https://www.w3schools.com/howto/howto_js_filter_table.asp -->
@@ -44,9 +44,9 @@ function filterFunc(input_id,col) {
   <tr><th width=20%>Address</th><th width=15%>devtype</th><th width=15%>Name</th><th width=15%>Info</th><th width=35%>Attributes</th></tr>
   % for dev in devs:  
   <tr>
-    <td><a href="/generic/${dev.address}">${dev.address}</a></td>
+    <td><a href="./generic/${dev.address}">${dev.address}</a></td>
     <td>${dev.devtype}</td>
-    <td><a href="/edit_metadata/${dev.address}">➠</a> ${dev.display_name}</td>
+    <td><a href="./edit_metadata/${dev.address}">➠</a> ${dev.display_name}</td>
     %if 'info' in dev.description.keys():
        <td>${dev.description['info']}</td>
     %else:
diff --git a/apps/dashboard/xaal/dashboard/templates/generic.mako b/apps/dashboard/xaal/dashboard/templates/generic.mako
index bdc635c754228507f5c3c4b2db74a692ab818ae7..b1412d6897c392fb2d44307c067cbf6f4eb96a50 100644
--- a/apps/dashboard/xaal/dashboard/templates/generic.mako
+++ b/apps/dashboard/xaal/dashboard/templates/generic.mako
@@ -28,7 +28,7 @@
 
 <h2>Attributes</h2>
 <div data-is="generic-attrs" xaal_addr="${dev.address}"></div>
-<script type="riot/tag" src="/static/tags/generic_attrs.tag"></script>
+<script type="riot/tag" src="../static/tags/generic_attrs.tag"></script>
 
 <h2>Meta Data</h2>
 <table width=100%>
@@ -37,4 +37,4 @@
   <tr><td>${k}</td><td>${dev.db[k]}</td></tr>
 % endfor   
 </table>
-<a href="/edit_metadata/${dev.address}">Edit meta-data</a>
+<a href="../edit_metadata/${dev.address}">Edit meta-data</a>
diff --git a/apps/dashboard/xaal/dashboard/templates/graph.mako b/apps/dashboard/xaal/dashboard/templates/graph.mako
new file mode 100644
index 0000000000000000000000000000000000000000..82f8f4cc54cf6aa478e3f63b3bf9f670bccaf128
--- /dev/null
+++ b/apps/dashboard/xaal/dashboard/templates/graph.mako
@@ -0,0 +1,122 @@
+<%inherit file="base.mako"/>
+    
+<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.13.0/moment.min.js"></script>
+<script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0"></script>
+<script src="https://cdn.jsdelivr.net/npm/hammerjs@2.0.8"></script>
+<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom@0.7.0"></script>
+
+
+
+
+
+<br/>
+<div class="content">
+    <div id="data">Warp10 datas for ${addr} daily</div>
+    <canvas id="chart"></canvas>
+</div>
+
+
+
+<script>
+
+//================ JS tools ====================================================
+// dumbs functions to mimic jQuery selectors
+var _ = function ( elem ) {
+  return document.querySelector( elem );
+}
+
+var __ = function ( elem ) {
+  return document.querySelectorAll( elem );
+}
+
+
+function update(data) {
+    //console.log(data);
+    //_('#data').innerHTML = "<pre>" + data +"</pre>";
+    clearData(chart);
+    addData(chart,data);
+}
+
+function clearData(chart) {
+  if (chart.hasOwnProperty('datasets')) {
+    chart.datasets.forEach((dataset) => {
+      dataset.data = [];
+    })
+  }
+  chart.data.labels=[];  
+  chart.update();
+}
+
+function load(addr) {
+  var getUrl = window.location;
+  var url = getUrl.protocol + "//" + getUrl.host + "/warp10/daily/"+addr;
+  console.log(url);
+  fetch(url)
+    .then(response => response.json())
+    .then(data => update(data))
+    .catch(err => console.log(err))
+}
+
+
+
+function addData(chart, data) {
+  data.forEach((kv) => {
+    chart.data.labels.push(kv[0]);
+    chart.data.datasets[0].data.push(kv[1]);
+    }
+  );
+  //chart.data.labels.push(label);
+  //chart.data.datasets.forEach((dataset) => {
+  //    dataset.data.push(data);
+  //});
+  chart.update();
+  chart.render();
+}
+
+
+
+var config = {
+  type: 'line',
+  data: {
+    datasets: [{
+      label: "Warp10 data",
+      borderColor: "#00bbd7",
+      pointRadius: 1,
+      borderWidth: 2,
+      lineTension: 0.2,
+    }]
+  },
+
+  options: {
+    responsive: true, 
+    //maintainAspectRatio: false,
+    scales: {
+      xAxes: [{
+        type: 'time',
+        time: {
+          parser: 'X',
+          displayFormats: { hour: 'H:mm'}
+        }
+      }],
+    },
+  }
+};
+
+
+var ctx = document.getElementById("chart").getContext("2d");
+chart=new Chart(ctx, config);
+
+function refresh() {
+  console.log('Loading datas');
+  load('${addr}');
+}
+
+
+refresh();
+/*
+setInterval(() => { 
+  refresh();
+  },1000 * 60);
+*/
+
+</script>
diff --git a/apps/dashboard/xaal/dashboard/templates/grid.mako b/apps/dashboard/xaal/dashboard/templates/grid.mako
index 54163ecb20c5d751ee62af144328cdf0d6640448..05f5c8d7e45cd39b5f6d4948a9c21b4d7d142719 100644
--- a/apps/dashboard/xaal/dashboard/templates/grid.mako
+++ b/apps/dashboard/xaal/dashboard/templates/grid.mako
@@ -1,90 +1,99 @@
 <%inherit file="base.mako"/>
 <%namespace name="widgets" file="widgets.mako" />
 
+<link href="../static/css/btns.css" rel="stylesheet">
+
 <div class="grid-background">
 <div class="grid">
 
   <div class="grid-box">
-    <div style="text-align:center;">
-      ${widgets.lamp('lamp_entree')}
-      ${widgets.lamp('lamp_couloir')}       
-    </div>
+    <b>Eclairage</b>
+      ${widgets.list_devices(['lamp_entree','lamp_couloir','lamp_salon'])}
   </div>
 
   <div class="grid-box">
-    <div style="text-align:center;">
-      ${widgets.lamp('lamp_salon')}
-      ${widgets.lamp('lamp_salle')}       
-    </div>
+    <b>Eclairage</b>
+      ${widgets.list_devices(['lamp_salle','lamp_cuisine','lamp_sdb','relay_spot'])}      
   </div>
 
   <div class="grid-box">
-    <div style="text-align:center;">
-      ${widgets.lamp('lamp_cuisine')}
-      ${widgets.lamp('lamp_sdb')}       
-    </div>
+    <b>Relais</b>
+      ${widgets.list_devices(['relay_pepper','relay_bouilloire'])}
   </div>
 
 
   <div class="grid-box">
     <div style="text-align:center;">
-      <b>Volet cuisine</b>
-     <span data-is="shutter" xaal_addr="2fe70f46-3ece-44d1-af34-2d82e10fb854"></span>
+     ${widgets.shutter('shutter_sdb')}
     </div>
   </div>
 
   <div class="grid-box">   
     <div style="text-align:center;">
-      <b>Volet SDB</b>
-     <span data-is="shutter" xaal_addr="e4b05165-be5d-46d5-acd0-4da7be1158ed"></span>
+     ${widgets.shutter('shutter_cuisine')}
     </div>
   </div>
 
   
-  
   <div class="grid-box">
-    <div style="text-align:center;">
-      ${widgets.lamp('lamp_test')}
-    </div>
+    <b>Température</b>
+    ${widgets.list_devices(['temp_netatmo','temp_owm','temp_bureau',])}
   </div>
 
   <div class="grid-box">
-    <b>Température</b>
-    ${widgets.list_thermometer(['temp_owm','temp_bureau'])}
+    <b>Humidité</b>
+    ${widgets.list_devices(['rh_netatmo','rh_owm','rh_bureau'])}
   </div>
 
+
   <div class="grid-box">
-    <b>Humidité</b>
-    ${widgets.list_hygrometer(['rh_owm','rh_bureau'])}
+    <b>Aquara</b>
+    ${widgets.list_devices(['temp_aqara1','rh_aqara1','press_aqara1'])}
+    ${widgets.list_devices(['temp_aqara2','rh_aqara2','press_aqara2'])}    
   </div>
 
- <div class="grid-box">
-  <div style="text-align:center;">
-    <b>Wall Plug</b>
-    <span data-is="powerrelay" xaal_addr="5e50a1ed-5290-4cdb-b00f-1f968eee4401"></span>
-    <br/>
-    <span data-is="powermeter" xaal_addr="5e50a1ed-5290-4cdb-b00f-1f968eee4402"></span>
+  
+  <div class="grid-box">
+    <b>Ouverture</b>
+    ${widgets.list_devices(['door1','door2','door3','door4'])}
   </div>
- </div>
 
 
-<div class="grid-box">
+
+  
+  <div class="grid-box">
+    <b>Consommations</b>
+    ${widgets.list_devices(['pmeter_spot','pmeter_robot','pmeter_bouilloire'])}
+  </div>
+
+  <div class="grid-box">
+    <b>Mouvement</b>
+    ${widgets.list_devices(['motion1','motion2','motion3','motion4','motion5'])}
+  </div>
+  
+  <div class="grid-box">
+    <b>CO2</b>
+    ${widgets.list_devices(['co2_1','co2_2','co2_3','co2_4'])}
+  </div>
+
+
+
+<!-- 
+<div class="grid-box two">
   <div style="text-align:center;">
-    <b>Test1</b>
-    <span data-is="lamp" xaal_addr="dde4ab86-076f-11e8-b7ec-00fec8f71301"></span>
-    <span data-is="lamp" xaal_addr="0a238b82-0760-11e8-b576-00fec8f71301"></span>
+    <iframe src="https://aal.enstb.org/grafana/d-solo/mNvuqkJmz/xaal-lab?refresh=5s&panelId=24&orgId=1" width="310" height="100" frameborder="0"></iframe>
+    <iframe src="https://aal.enstb.org/grafana/d-solo/mNvuqkJmz/xaal-lab?refresh=1m&panelId=27&orgId=1" width="310" height="100" frameborder="0"></iframe>    
   </div>
  </div>
  
+-->
 
-  <div class="grid-box two">
-    <div data-is="generic-attrs" xaal_addr="7b81512c-0a96-11e8-ad38-3c77e618c6f7"></div>
-  </div>
-
+  <!--
   <div class="grid-box two" style="align:center;">
-    	<!-- img src="http://10.77.3.51/video3.mjpg" width=250 -->
+    	<img src="http://10.77.3.51/video3.mjpg" width=250>
   </div>
-
+  -->
+  
   <div class="grid-box" style="text-align:center;">
     <br/><br/><br/>
       <span data-is="clock"/>
@@ -94,13 +103,18 @@
 </div> <!-- end of grid -->
 </div><!-- end of grib background -->
 
-<script type="riot/tag" src="/static/tags/powerrelay.tag"></script>
-<script type="riot/tag" src="/static/tags/hygrometer.tag"></script>
-<script type="riot/tag" src="/static/tags/thermometer.tag"></script>
-<script type="riot/tag" src="/static/tags/powermeter.tag"></script>
-<script type="riot/tag" src="/static/tags/lamp.tag"></script>
-<script type="riot/tag" src="/static/tags/shutter.tag"></script>
+<script type="riot/tag" src="../static/tags/powerrelay.tag"></script>
+<script type="riot/tag" src="../static/tags/hygrometer.tag"></script>
+<script type="riot/tag" src="../static/tags/thermometer.tag"></script>
+<script type="riot/tag" src="../static/tags/powermeter.tag"></script>
+<script type="riot/tag" src="../static/tags/lamp.tag"></script>
+<script type="riot/tag" src="../static/tags/shutter.tag"></script>
+<script type="riot/tag" src="../static/tags/barometer.tag"></script>
+<script type="riot/tag" src="../static/tags/co2meter.tag"></script>
+<script type="riot/tag" src="../static/tags/motion.tag"></script>
+<script type="riot/tag" src="../static/tags/door.tag"></script>
+
 
 
-<script type="riot/tag" src="/static/tags/generic_attrs.tag"></script>
-<script type="riot/tag" src="/static/tags/clock.tag"></script>
+<script type="riot/tag" src="../static/tags/generic_attrs.tag"></script>
+<script type="riot/tag" src="../static/tags/clock.tag"></script>
diff --git a/apps/dashboard/xaal/dashboard/templates/menu.mako b/apps/dashboard/xaal/dashboard/templates/menu.mako
index 05de5d5934a30a0890ccf0d82221360dff4a2fa1..2ddf696d9dabbf4a341a02d0208646d7263347f6 100644
--- a/apps/dashboard/xaal/dashboard/templates/menu.mako
+++ b/apps/dashboard/xaal/dashboard/templates/menu.mako
@@ -1,12 +1,19 @@
-  <!-- Menu -->
+<%
+    menu = [('devices'   ,'Eléments'),
+            ('grid'      ,'Général'),
+           ]
+%>
+   
+<!-- Menu -->
   <ul class="menu">
     <li><a href="#" onclick="openNav()">&#9776;</a></li>     
-% for item in menu.get():
-  %  if item.has_key('active'):
-    <li class="active"><a href="${item['url']}">${item['value']}</a></li>
-  %  else:
-    <li><a href="${item['url']}">${item['value']}</a></li>
-  % endif
+% for item in menu:
+%   if item[0] == active_menu:    
+        <li class="active"><a href="/${item[0]}">${item[1]}</a></li>
+%   else:
+        <li><a href="/${item[0]}">${item[1]}</a></li>
+%   endif
+        
 % endfor
   </ul>
-  <!-- EOF Menu -->
+<!-- EOF Menu -->
diff --git a/apps/dashboard/xaal/dashboard/templates/widgets.mako b/apps/dashboard/xaal/dashboard/templates/widgets.mako
index 532c83c871be5c1ef535d1ae19a1399bac8b6c34..076751923b8c026b7a95bbf4541b64788f64ad07 100644
--- a/apps/dashboard/xaal/dashboard/templates/widgets.mako
+++ b/apps/dashboard/xaal/dashboard/templates/widgets.mako
@@ -1,58 +1,117 @@
 <%def name="thermometer(addr)">
-<a href="/generic/${addr}">
+<a href="./warp10/graph/${addr}">
   <div data-is="thermometer" xaal_addr=${addr}></div>
 </a>
 </%def>
 
 
 <%def name="hygrometer(addr)">
-<a href="/generic/${addr}">
+<a href="./warp10/graph/${addr}">
   <div data-is="hygrometer" xaal_addr=${addr}></div>
 </a>
 </%def>
 
+<%def name="powerrelay(addr)">
+  <div data-is="powerrelay" xaal_addr=${addr}></div>
+</%def>
+
+<%def name="lamp_(addr)">
+  <div data-is="lamp" xaal_addr=${addr}></div>
+</%def>
+
+
+<%def name="generic(addr)">
+  <div data-is="generic-attrs" xaal_addr=${addr}></div>
+</%def>
+
+
+<%def name="powermeter(addr)">
+<a href="./warp10/graph/${addr}">
+  <div data-is="powermeter" xaal_addr=${addr}></div>
+</a>
+</%def>
+
+<%def name="barometer(addr)">
+<a href="./warp10/graph/${addr}">
+  <div data-is="barometer" xaal_addr=${addr}></div>
+</a>
+</%def>
+
+<%def name="co2meter(addr)">
+<a href="./warp10/graph/${addr}">
+  <div data-is="co2meter" xaal_addr=${addr}></div>
+</a>
+</%def>
+
+
+<%def name="motion(addr)">
+  <div data-is="motion" xaal_addr=${addr}></div>
+</%def>
+
+<%def name="door(addr)">
+  <div data-is="door" xaal_addr=${addr}></div>
+</%def>
 
-<%def name="lamp(nickname)">
+
+<%def name="shutter(nickname)">
 <% dev = devices.fetch_one_kv('nickname',nickname) %>
 % if dev:
-  <b>${dev.get_kv('name')}</b><a href="./generic/${dev.address}">&nbsp;</a>
-  <span data-is="lamp" xaal_addr=${dev.address}></span>
+  <b>${dev.display_name}</b>
+  <span data-is="shutter" xaal_addr=${dev.address}></span>
 % else:
   device not found: <b>${nickname}</b>
 % endif
 </%def>
 
 
-<%def name="list_thermometer(values)">
-<table>
-% for nick in values:
-<% dev = devices.fetch_one_kv('nickname',nick) %>
+<%!
+  def tag(dev):
+      type_ = dev.devtype
+      if type_.startswith('thermometer.')   : return 'thermometer'
+      if type_.startswith('hygrometer.')    : return 'hygrometer'
+      if type_.startswith('shutter.')       : return 'shutter'
+      if type_.startswith('lamp.')          : return 'lamp_'
+      if type_.startswith('powerrelay.')    : return 'powerrelay'
+      if type_.startswith('powermeter.')    : return 'powermeter'
+      if type_.startswith('barometer.')     : return 'barometer'
+      if type_.startswith('co2meter.')      : return 'co2meter'
+      if type_.startswith('motion.')        : return 'motion'  
+      if type_.startswith('door.')          : return 'door'
+  
+      return 'generic'
+%>
+
+
+<%def name="device(nickname)">
+<% dev = devices.fetch_one_kv('nickname',nickname) %>
 % if dev:
-<tr>
-  <td>${dev.get_kv('name')}</td>
-  <td>
-    <a href="./generic/${dev.address}">
-      <span data-is="thermometer" xaal_addr=${dev.address}>
-    </a>
-  </td>
-</tr>
+    ${ self.template.get_def(tag(dev)).render(dev.address) } 
+% else:
+     Device not found ${nickname}
+% endif
+</%def>
+
+<%def name="device_addr(addr)">
+<% dev = devices.get_with_addr(addr) %>
+% if dev:
+     ${ self.template.get_def(tag(dev)).render(dev.address) }
+% else:
+     Device not found [${addr}]
 % endif
-% endfor
-</table>
 </%def>
 
 
-<%def name="list_hygrometer(values)">
-<table>
+<%def name="list_devices(values)">
+<table width=98%>
 % for nick in values:
 <% dev = devices.fetch_one_kv('nickname',nick) %>
 % if dev:
 <tr>
-  <td>${dev.get_kv('name')}</td>
   <td>
-    <a href="./generic/${dev.address}">
-      <span data-is="hygrometer" xaal_addr=${dev.address}>
-    </a>
+        <a href="./generic/${dev.address}">➠</a>${dev.display_name}
+  </td>
+  <td>
+    ${ self.template.get_def(tag(dev)).render(dev.address) } 
   </td>
 </tr>
 % endif
diff --git a/apps/tools/xaal/tools/isalive.py b/apps/tools/xaal/tools/isalive.py
index 8bee1a03a4a67db1f9df0f75f0bdd3f8fd871c6a..dde7774c82b4c39529f7ab0808d149212597c3f9 100644
--- a/apps/tools/xaal/tools/isalive.py
+++ b/apps/tools/xaal/tools/isalive.py
@@ -49,12 +49,13 @@ class Scanner:
         print("="*70)
         self.loop()
         print("="*70)
+        print("Found %d devices" % len(self.seen))
 
     def loop(self):
         t0 = time.time()
         while 1:
             self.eng.loop()
-            if time.time() > (t0 + 1):
+            if time.time() > (t0 + 2):
                 break
 
     def parse_answer(self,msg):
diff --git a/apps/tools/xaal/tools/log.py b/apps/tools/xaal/tools/log.py
index feedf118ce833d5ec75a68f51074a29b7115b8c5..5b61424b8101e54cf36ebcc668663fb3f7d5ba3b 100644
--- a/apps/tools/xaal/tools/log.py
+++ b/apps/tools/xaal/tools/log.py
@@ -8,8 +8,8 @@ helpers.set_console_title("xaal-log")
 def print_evt(msg):
     if msg.is_alive():
         return
-    if msg.is_attributes_change() or msg.is_notify():
-        print("%s %s %s %s" % (time.ctime(),msg.source,msg.devtype,msg.body))
+    if msg.is_notify():
+        print("%s %s %s %s %s" % (time.ctime(),msg.source,msg.devtype,msg.action,msg.body))
 
 
 def main():
diff --git a/devices/loggers/warp10/xaal/warp10/delete.py b/devices/loggers/warp10/xaal/warp10/delete.py
new file mode 100644
index 0000000000000000000000000000000000000000..0c149e594055184c989019f0182b5e2376011937
--- /dev/null
+++ b/devices/loggers/warp10/xaal/warp10/delete.py
@@ -0,0 +1,22 @@
+from xaal.lib import config,tools
+import urllib3
+import sys
+
+
+PACKAGE_NAME = "xaal.warp10"
+
+def main():
+    serie = sys.argv[1]
+    cfg = tools.load_cfg_or_die(PACKAGE_NAME)['config']
+    http = urllib3.PoolManager()
+    DATA_BUF=""
+    url = '/'.join(cfg['url'].split('/')[:-1]) + '/delete?deleteall&selector=%s' % sys.argv[1]
+    print(url)
+    rsp = http.request('GET',url,headers={'X-Warp10-Token':cfg['token']},body=DATA_BUF,retries=2)
+    print(rsp.data)
+
+
+
+if __name__ == '__main__':
+    main()
+    
diff --git a/devices/notifications/pushbullet/xaal/pushbullet/dev.py b/devices/notifications/pushbullet/xaal/pushbullet/dev.py
index 9d3638d555028d8413b0bbb7d39a6f11fd3cff6b..94d165c6851b40e6be6333e87adca4058f279cc7 100644
--- a/devices/notifications/pushbullet/xaal/pushbullet/dev.py
+++ b/devices/notifications/pushbullet/xaal/pushbullet/dev.py
@@ -10,21 +10,22 @@ PACKAGE_NAME = "xaal.pushbullet"
 logger = logging.getLogger(PACKAGE_NAME)
 
 
-push_bullet = None
+push_bullets = []
 def register_device(engine):
     global push_bullet
     cfg = tools.load_cfg(PACKAGE_NAME)
     if not cfg:
         logger.info('Missing config file, building a new one')
         cfg = tools.new_cfg(PACKAGE_NAME)
-        cfg['config']['key']=''
+        cfg['config']['keys']=''
         cfg.write()
 
-    key = cfg['config'].get('key',None)
-    if not key:
-        logger.info('Please setup the Pushbullet Key')
+    keys = cfg['config'].get('keys',None)
+    if not keys:
+        logger.info('Please setup the Pushbullet keys')
         return
-    push_bullet = Pushbullet(key)        
+    for k in keys:
+        push_bullets.append(Pushbullet(k))
     info = "%s@%s" % (PACKAGE_NAME,platform.node())
     dev = Device("notification.pushbullet")
     dev.address     = cfg['config']['addr']
@@ -38,17 +39,16 @@ def register_device(engine):
     atexit.register(notify,info,'shutdown..')
                 
 def notify(_title,_msg):
-    global push_bullet
-    if push_bullet:
-        try:
-            push_bullet.push_note(_title,_msg)
-        except Exception as err:
-            print("Pushbullet exception: {0}".format(err))
-            # some error can occur on a broken link, just try to resend
-            time.sleep(0.5)
-            push_bullet.push_note(_title,_msg)
-
-
+    global push_bullets
+    if push_bullets != []:
+        for pb in push_bullets:
+            try:
+                pb.push_note(_title,_msg)
+            except Exception as err:
+                print("Pushbullet exception: {0}".format(err))
+                # some error can occur on a broken link, just try to resend
+                time.sleep(0.5)
+                pb.push_note(_title,_msg)
 
 
 def setup(engine):
diff --git a/devices/protocols/Aqara/README.rst b/devices/protocols/Aqara/README.rst
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5fd80c7b2efae79e1dc8d7eee95b1669cd7a634e 100644
--- a/devices/protocols/Aqara/README.rst
+++ b/devices/protocols/Aqara/README.rst
@@ -0,0 +1,32 @@
+xAAL Aqara Gateway
+==================
+
+
+Install & Config
+----------------
+- Install with python setup.py develop or install.
+- Enable local network on the Aqara Gateway with the Mi Home
+  Android or iOS app. You can follow this manual: 
+  https://www.domoticz.com/wiki/Xiaomi_Gateway_(Aqara)
+  store the secret key somewhere.
+- Run the xAAL gateway with: python -m xaal.aqara. The gateway
+  should detect all Aqara devices on your local network.
+- To enable quick discovery and control devices (switches, leds..)
+  edit the config file ~/.xaal/xaal.aqara.ini and add the key
+  like this:
+  
+  [devices]
+    [[xxxxxxxxxxxx]]
+       base_addr = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx
+       model = gateway
+       secret = ydt5xis45x7k5x1x
+       
+
+Notes
+-----
+- xAAL gateway supports more than one Aqara Gateway (hub) on the
+  network make sure to set a secret key to each hub.
+- xAAL gateway supports most Aqara devices, feel free to edit (and
+  submit) xaal/aqara/devices.py if you own a unsupported device.
+  
+  
diff --git a/devices/protocols/Aqara/xaal/aqara/devices.py b/devices/protocols/Aqara/xaal/aqara/devices.py
index 8f5553da131e6264ff7bd4c10474e94f984080dd..208c38c244bd7e57a9b59f286d295624f88e9355 100644
--- a/devices/protocols/Aqara/xaal/aqara/devices.py
+++ b/devices/protocols/Aqara/xaal/aqara/devices.py
@@ -14,15 +14,17 @@ AQARA_ENCRYPT_IV = b'\x17\x99\x6d\x09\x3d\x28\xdd\xb3\xba\x69\x5a\x2e\x6f\x58\x5
 logger = logging.getLogger(__name__)
 
 class AqaraDev(object):
-    def __init__(self,sid,model,base_addr):
+    def __init__(self,sid,model,base_addr,xaal_gw):
         self.sid = sid
         self.model = model
         self.base_addr = base_addr
-        self.devices = []
+        self.xaal_gw = xaal_gw
+        # xAAL embeded devices
+        self.devices = [] 
         logger.info('New AqaraDevice %s %s' % (model,sid))
         self.setup()
         self.init_properties()
-
+  
     def setup(self):
         logger.warning('Please overide setup()')
 
@@ -43,6 +45,7 @@ class AqaraDev(object):
         if cmd in ['report','heartbeat']:
             pload = pkt.get('data',None)
             if pload:
+                # json in json really ? grr
                 data = ujson.decode(pload)
                 if cmd == 'report':
                     self.on_report(data)
@@ -55,7 +58,7 @@ class AqaraDev(object):
         logger.info('Unhandled report %s' % data)
 
     def on_heartbeat(self,data):
-        print(data)
+        logger.info('Unhandled heartbeat %s' % data)
 
 
 class Switch(AqaraDev):
@@ -106,7 +109,6 @@ class Motion(AqaraDev):
         self.devices.append(devices.motion(self.base_addr+'00'))
 
     def on_report(self,data):
-        print(data)
         val = data.get('status',None)
         if val and val == 'motion':
             self.devices[0].attributes['presence'] = True
@@ -134,24 +136,47 @@ class Vibration(AqaraDev):pass
 
 class Cube(AqaraDev):pass
 
+class RelayController(AqaraDev):pass
+
+class WaterLeak(AqaraDev):
+    # no device yet on this
+
+    def on_report(self,data):
+        status = data.get('status',None)
+        if status and status == 'leak':
+            logger.warning('Leaking..')
+        if status and status == 'no_leak':
+            logger.warning('No leaking')
+
 
 class Gateway(AqaraDev):
     def setup(self):
+        self.sids = []
         self.ip = None
         self.token = None
+        self.ready = False
         self.rgb = None
+        self._blink_color = 0
         self.connect()
         lamp = devices.lamp(self.base_addr+'00')
         lamp.methods['on'] = self.lamp_on
         lamp.methods['off'] = self.lamp_off
         lamp.methods['rand']   = self.lamp_rand
+        lamp.methods['blink']   = self.lamp_blink
         self.devices.append(lamp)
 
         siren = Device('siren.sound',self.base_addr+'01')
         siren.methods['play'] = self.siren_play
         siren.methods['stop'] = self.siren_stop
+        #siren.methods['debug'] = self.debug
         self.devices.append(siren)
 
+    def debug(self):
+        import pdb;pdb.set_trace()
+
+    #========================================================================
+    ## GW Unicast methods
+    #========================================================================  
     @property
     def secret(self):
         return self._secret
@@ -171,33 +196,92 @@ class Gateway(AqaraDev):
 
     def send(self,pkt):
         if not self.ip:
-            logger.warning("GW not found, please wait")
+            logger.warning("GW IP not found yet, please wait")
             return
         try:
-            print(pkt)
+            #print(pkt)
             self.sock.sendto(pkt,(self.ip,GW_PORT))
             ans = self.sock.recv(65507)
             return ans
         except Exception as e:
             logger.warning(e)
 
-    def write(self,data = {}):
+    def send_cmd(self,cmd,sid,data={}):
+        if not self.token :
+            logger.warning("No token yet, please wait")
+            return
+        if not self.secret:
+            logger.warn("Please set the secret key in cfg file")
+            return
         key = self.make_key()
         data.update({"key":key})
-        pload = {"cmd":"write",
-                 "sid": self.sid,
-                 "data" : data
+        pload = {"cmd":   cmd,
+                 "sid":   sid,
+                 "data":  data
                 }
         pkt = ujson.encode(pload).encode('utf8')
         return self.send(pkt)
 
+
+    #========================================================================
+    ## Gateway Unicast commands
+    #========================================================================  
+    def write(self,data = {}):
+        """send command to the GW, used for siren, lamp, radio?"""
+        pkt = self.send_cmd("write",self.sid,data)
+        self.on_receive(pkt)
+
+    def get_id_list(self):
+        """ retreive the devices list"""
+        pkt = self.send_cmd("get_id_list",self.sid)
+        self.on_receive(pkt)
+
+    def discover(self):
+        """
+        query device list and ask for a read, on each sid
+
+        The doc say we should use {"cmd": "discovery"} instead of get_id_list + 
+        read, but I always have a discory error => "missing sid"
+        http://docs.opencloud.aqara.com/en/development/gateway-LAN-communication/
+        """
+        self.get_id_list()
+        for sid in self.sids:
+            pkt = self.send_cmd("read",sid)
+            self.on_receive(pkt)
+
+    def on_receive(self,pkt):         
+        if not pkt: return 
+
+        pload = ujson.decode(pkt)
+        cmd = pload.get('cmd',None)
+
+        if cmd == 'get_id_list_ack':
+            data = pload.get('data','[]')
+            self.sids = ujson.decode(data)
+
+        if cmd == 'read_ack':
+            model = pload.get('model',None)
+            sid = pload.get('sid',None)
+            dev = self.xaal_gw.get_device(sid,model)
+            if dev:
+                data = ujson.decode(pload.get('data','{}'))
+                dev.on_report(data)
+            else:
+                logger.warning("Unknow device %s" % pload)
+
+        if cmd == 'write_ack':
+            print(pkt)
+
+
+    #========================================================================
     ## RGB Leds 
+    #========================================================================
     def get_rgb(self,red,green,blue,brightness=0xFF):
         return brightness<<24|( red << 16)|( green << 8)|blue
 
     def lamp_set(self,value):
         data = {"rgb" : value}
-        print(self.write(data))
+        self.write(data)
 
     def lamp_on(self):
         color = self.rgb or self.get_rgb(255,170,170)
@@ -214,30 +298,62 @@ class Gateway(AqaraDev):
         rgb = self.get_rgb(red,green,blue)
         self.lamp_set(rgb)
 
-    ## Siren go here
-    def siren_play(self,_sound=26,_volume=5):
+    def _red(self):
+        self.lamp_set(self.get_rgb(255,0,0))
+
+    def _white(self):
+        self.lamp_set(self.get_rgb(255,255,255))
+        
+    def _lamp_blink(self):
+        if self._blink_color ==0:
+            self._red()
+            self._blink_color = 1
+        else:
+            self._white()
+            self._blink_color = 0
+
+    def lamp_blink(self):
+        eng = self.devices[0].engine
+        eng.add_timer(self.lamp_off,20,0)
+        eng.add_timer(self._lamp_blink,1,15)
+
+    #========================================================================
+    ## Siren
+    #========================================================================  
+    def siren_play(self,_sound=2,_volume=5):
+        logger.info('Playing %s %s' % (_sound,_volume))
         data = {
-                "mid" : _sound,
-                "volume": _volume,
+                "mid" : int(_sound),
+                "volume": int(_volume),
                 }
         self.write(data)
 
     def siren_stop(self):
         data = { "mid" : 999 }
-        print(self.write(data))
+        self.write(data)
+
 
+    #========================================================================
+    ## GW Mutlicast messages handlers
+    #========================================================================  
     def parse(self,pkt):
-        # the Gateway need to parse the token addtionnal parameter
-        cmd = pkt.get('cmd',None)
-        if cmd == 'heartbeat':
-            token = pkt.get('token',None)
-            if token: self.token = token
+        # extract the token before normal parsing
+        token = pkt.get('token',None)
+        if token: 
+            self.token = token
         AqaraDev.parse(self,pkt)
 
     def on_heartbeat(self,data):
         ip = data.get('ip',None)
         if ip and ip != self.ip:
             self.ip = ip
+            logger.info("GW IP found: %s" % ip)
+        
+        if not self.ready :
+            if self.token and self.ip:
+                self.ready = True
+                self.discover()
+
 
     def on_report(self,data):
         rgb = data.get('rgb',None)
diff --git a/devices/protocols/Aqara/xaal/aqara/gw.py b/devices/protocols/Aqara/xaal/aqara/gw.py
index 0175f6ab91ed6f2dc09cf2d1a940da86211b4b28..0f8ec8d3e71909d1465922b47e7b6b3e230c8142 100644
--- a/devices/protocols/Aqara/xaal/aqara/gw.py
+++ b/devices/protocols/Aqara/xaal/aqara/gw.py
@@ -29,6 +29,10 @@ def find_device_class(model):
         return devices.Vibration
     if model == 'sensor_cube.aqgl01':
         return devices.Cube
+    if model == 'sensor_wleak.aq1':
+        return devices.RelayController
+    if model == 'lumi.ctrl_dualchn':
+        return devices.RelayController
     return None
 
 class GW(gevent.Greenlet):
@@ -52,47 +56,54 @@ class GW(gevent.Greenlet):
     def add_device(self,sid,model,base_addr):
         klass = find_device_class(model)
         if klass:
-            dev = klass(sid,model,base_addr)
+            dev = klass(sid,model,base_addr,self)
             self.engine.add_devices(dev.devices)
             self.devices.update({sid:dev})
             return dev
         else:
-            logger.info('Unsupported device %s/%s' % (model,sid))
+            logger.info('Unsupported device [%s]/[%s]' % (model,sid))
             return None
 
     def setup(self):
         self.aqara = AqaraConnector()
-        devs = self.cfg['devices']
-        for sid in devs:
-            cfg = devs[sid]
-            model = cfg.get('model',None)
-            base_addr = cfg.get('base_addr',None)
-            # TBD : Merge this w/ handle new device
+    
+    def get_device(self,sid,model):
+        # Already running device ? 
+        if sid in self.devices.keys():
+            return self.devices[sid]
+        # Already known device ? 
+        elif sid in self.cfg['devices'].keys():
+            cfg = self.cfg['devices'][sid]
+            model_old = cfg.get('model',None)
+            base_addr = cfg.get('base_addr',None)          
+            dev = None
+            if model != model_old:
+                logger.warn("Device %s wrong model" % sid)
             if model and base_addr:
                 dev = self.add_device(sid,model,base_addr)
                 if dev and model == 'gateway':
-                    dev.secret = devs[sid].get('secret',None)
-    
+                    dev.secret = cfg.get('secret',None)
+            return dev
+        # Still not found ? => new device
+        else:
+            base_addr = tools.get_random_uuid()[:-2]
+            dev = self.add_device(sid,model,base_addr)
+            if dev:
+                cfg = {'base_addr' : base_addr,'model':model}
+                self.cfg['devices'].update({sid:cfg})
+            return dev
+
     def _run(self):
         while 1:
             pkt = self.aqara.receive()
             if pkt:
-                self.handle(pkt)
+                self.on_receive(pkt)
 
-    def handle(self,pkt):
+    def on_receive(self,pkt):
         sid = pkt.get('sid',None)
         if not sid: return
-        dev = None
-        if sid in self.devices.keys():
-            dev = self.devices[sid]
-        else:
-            model = pkt.get('model',None)
-            if not model:return
-            base_addr = tools.get_random_uuid()[:-2]
-            dev = self.add_device(sid,model,base_addr)
-            if dev:
-                cfg = {'base_addr' : base_addr,'model':model}
-                self.cfg['devices'].update({sid:cfg})
+        model = pkt.get('model',None)
+        dev = self.get_device(sid,model)
         if dev:
             dev.parse(pkt)
 
diff --git a/devices/protocols/Aqara/xaal/aqara/network.py b/devices/protocols/Aqara/xaal/aqara/network.py
index ff4aceb1f6412605bad5603d69977a9fa8ce15b0..489239d331284df858fc4a3f69771e4b86d3189e 100644
--- a/devices/protocols/Aqara/xaal/aqara/network.py
+++ b/devices/protocols/Aqara/xaal/aqara/network.py
@@ -11,6 +11,12 @@ logger = logging.getLogger(__name__)
 
 
 class AqaraConnector:
+    """
+    Aqara Device Report/Heartbeat connector, used only to receive event, if you want to send a command,
+    you must send a unicast datagram to the right Aqara GW.
+
+    Please note, this isn't the Gateway discovery
+    """
     def __init__(self):
         self.nc = network.NetworkConnector('224.0.0.50',9898,10)
         self.nc.connect()
@@ -19,6 +25,7 @@ class AqaraConnector:
         buf = self.nc.receive()
         if buf:
             try:
+                #logger.warning(buf)
                 return ujson.decode(buf)
             except ValueError:
                 logger.debug('JSON decoder Error %s' % buf)
diff --git a/devices/protocols/Edisio/README.rst b/devices/protocols/Edisio/README.rst
index cc6964443a14368f3d0833646b5cd8c312ac5924..6f01a21e748cde214afbe9e907fed9a407a6b3da 100644
--- a/devices/protocols/Edisio/README.rst
+++ b/devices/protocols/Edisio/README.rst
@@ -30,4 +30,10 @@ EE = END of Data
 2018-09-27 15:38:09 i7 xaal.edisio[18674] DEBUG [16] 6c 76 63 06 73 74 2b 03 01 1b 01 00 03 64 0d 0a 
 2018-09-27 15:38:09 i7 xaal.edisio[18674] DEBUG [16] 6c 76 63 06 73 74 2b 03 01 1b 01 00 03 64 0d 0a 
 2018-09-27 15:38:09 i7 xaal.edisio[18674] DEBUG [16] 6c 76 63 06 73 74 2b 03 01 1b 01 00 03 64 0d 0a 
-2018-09-27 15:38:09 i7 xaal.edisio[18674] DEBUG [16] 6c 76 63 06 73 74 2b 03 01 1b 01 00 03 64 0d 0a 
\ No newline at end of file
+2018-09-27 15:38:09 i7 xaal.edisio[18674] DEBUG [16] 6c 76 63 06 73 74 2b 03 01 1b 01 00 03 64 0d 0a 
+
+Config
+======
+- Edit ~/.xaal/xaal.edisio.ini according to your needs, mainly change the serial port, by default
+  everything else should be Ok.
+
diff --git a/devices/protocols/KNX/xaal/knx/bindings.py b/devices/protocols/KNX/xaal/knx/bindings.py
index e80768bf001ba061a2c841fc3df7c506e8ea69df..1e823bb419b4cae643407f39ff7727473d9a927d 100644
--- a/devices/protocols/KNX/xaal/knx/bindings.py
+++ b/devices/protocols/KNX/xaal/knx/bindings.py
@@ -21,16 +21,24 @@ def on_off(attribute,dpt,data):
 
 def round_(attribute,dpt,data):
     val = dpts.decode[dpt](data)
-    attribute.value = round(val)
+    if val!=None:
+        attribute.value = round(val)
 
 def set_(attribute,dpt,data):
     val = dpts.decode[dpt](data)
-    attribute.value = val
+    if val!=None:
+        attribute.value = val
 
+def mul1000_(attribute,dpt,data):
+    val = dpts.decode[dpt](data)
+    if val!=None:
+        attribute.value = round(val * 1000)
+        
 funct = {
     "bool"     : bool_,
     "bool_inv" : bool_inv,
+    "on_off"   : on_off,
     "round"    : round_,
     "set"      : set_,
-    "on_off"   : on_off,
-}
\ No newline at end of file
+    "mul1000"  : mul1000_,
+}
diff --git a/devices/protocols/KNX/xaal/knx/devices.py b/devices/protocols/KNX/xaal/knx/devices.py
index 2a02e2f518d91f307c4e3abf392684d4b34db027..c4d8a41fa2d651d9ec855cd23571457168699c83 100644
--- a/devices/protocols/KNX/xaal/knx/devices.py
+++ b/devices/protocols/KNX/xaal/knx/devices.py
@@ -22,7 +22,6 @@ class KNXDev:
         self.dev = None
         self.setup()
 
-
     def setup(self):
         logger.warn("Please define setup() in this device")
 
@@ -82,7 +81,34 @@ class Switch(KNXDev):
             self.bind_attribute(self.dev.get_attribute('position'),state,funct['bool'],'1')
             self.dev.info = "KNX %s"  % state
 
+class Shutter(KNXDev):
+    def setup(self):
+        self.dev = devices.shutter(self.addr)
+        up_down  = self.cfg.get('updown_cmd',None)
+        stop     = self.cfg.get('stop_cmd',None)
+        if up_down:
+            self.dev.add_method('up',self.write(up_down,'1',0))
+            self.dev.add_method('down',self.write(up_down,'1',1))
+        if stop:
+            self.dev.add_method('stop',self.write(stop,'1',1))
+
 
+class Shutter_position(KNXDev):
+    def setup(self):
+        self.dev = devices.shutter_position(self.addr)
+        up_down  = self.cfg.get('updown_cmd',None)
+        stop     = self.cfg.get('stop_cmd',None)
+        position = self.cfg.get('position_cmd',None)
+        if up_down:
+            self.dev.add_method('up',self.write(up_down,'1',0))
+            self.dev.add_method('down',self.write(up_down,'1',1))
+        if stop:
+            self.dev.add_method('stop',self.write(stop,'1',1))
+        if position:
+            self.dev.add_method('position',self.write(position,'1',1))
+
+
+            
 # =============================================================================
 # Sensors 
 # =============================================================================
@@ -90,15 +116,78 @@ class PowerMeter(KNXDev):
     def setup(self):
         self.dev = devices.powermeter(self.addr)
         self.dev.unsupported_attributes = ['devices']
+        self.dev.del_attribute(self.dev.get_attribute('devices'))
         power   = self.cfg.get('power',None)
         p_dpt   = self.cfg.get('power_dpt','9')
         p_mod   = self.cfg.get('power_mod','set')
         if power:
             self.bind_attribute(self.dev.get_attribute('power'),power,funct[p_mod],p_dpt)
+        else:
+            self.dev.del_attribute(self.dev.get_attribute('power'))
         energy = self.cfg.get('energy',None)
-        e_dpt  = self.cfg.get('energy_dpt','9')
+        e_dpt  = self.cfg.get('energy_dpt','13')
         e_mod  = self.cfg.get('energy_mod','set')
         if energy:
             self.bind_attribute(self.dev.get_attribute('energy'),energy,funct[e_mod],e_dpt)
+        else:
+            self.dev.del_attribute(self.dev.get_attribute('energy'))
         self.dev.info = "KNX %s"  % (power or energy)
-        
\ No newline at end of file
+        
+class Thermometer(KNXDev):
+    def setup(self):
+        self.dev = devices.thermometer(self.addr)
+        temperature = self.cfg.get('temperature',None)
+        t_dpt       = self.cfg.get('temperature_dpt','9')
+        t_mod       = self.cfg.get('temperature_mod','set')
+        if temperature:
+            self.bind_attribute(self.dev.get_attribute('temperature'),temperature,funct[t_mod],t_dpt)
+        self.dev.info = "KNX %s" % temperature
+
+class Hygrometer(KNXDev):
+    def setup(self):
+        self.dev = devices.hygrometer(self.addr)
+        humidity = self.cfg.get('humidity',None)
+        h_dpt    = self.cfg.get('humidity_dpt','5.001')
+        h_mod    = self.cfg.get('humidity_mod','round')
+        if humidity:
+            self.bind_attribute(self.dev.get_attribute('humidity'),humidity,funct[h_mod],h_dpt)
+        self.dev.info = "KNX %s" % humidity
+
+class CO2Meter(KNXDev):
+    def setup(self):
+        self.dev = devices.co2meter(self.addr)
+        co2      = self.cfg.get('co2',None)
+        c_dpt    = self.cfg.get('co2_dpt','9')
+        c_mod    = self.cfg.get('co2_mod','round')
+        if co2:
+            self.bind_attribute(self.dev.get_attribute('co2'),co2,funct[c_mod],c_dpt)
+        self.dev.info = "KNX %s" % co2
+
+class Luxmeter(KNXDev):
+    def setup(self):
+        self.dev = devices.luxmeter(self.addr)
+        illuminance = self.cfg.get('illuminance',None)
+        l_dpt       = self.cfg.get('illuminance_dpt','7')
+        l_mod       = self.cfg.get('illuminance_mod','set')
+        if illuminance:
+            self.bind_attribute(self.dev.get_attribute('illuminance'),illuminance,funct[l_mod],l_dpt)
+        self.dev.info = "KNX %s" % illuminance
+
+class Lightgauge(KNXDev):
+    def setup(self):
+        self.dev = devices.lightgauge(self.addr)
+        brightness = self.cfg.get('brightness',None)
+        b_dpt       = self.cfg.get('brightness_dpt','5.001')
+        b_mod       = self.cfg.get('brightness_mod','round')
+        if brightness:
+            self.bind_attribute(self.dev.get_attribute('brightness'),brightness,funct[b_mod],b_dpt)
+        self.dev.info = "KNX %s" % brightness 
+
+class Motion(KNXDev):
+    def setup(self):
+        self.dev = devices.motion(self.addr)
+        state = self.cfg.get('state',None)
+        if state:			
+            self.bind_attribute(self.dev.get_attribute('presence'),state,funct['bool'],'1')
+        self.dev.info = "KNX %s" % state
+
diff --git a/devices/protocols/KNX/xaal/knx/knxrouter.py b/devices/protocols/KNX/xaal/knx/knxrouter.py
index c949879ef9716f9f47d34b857fe001dfd4ecdcc1..f01965793ed2283902a4c9b56c6476a3c415e8b4 100644
--- a/devices/protocols/KNX/xaal/knx/knxrouter.py
+++ b/devices/protocols/KNX/xaal/knx/knxrouter.py
@@ -49,7 +49,8 @@ class KNXcEMI:
 
     def parse(self,buf):
         bytes_ = bytearray(buf)
-        if len(bytes_) < 17:
+        #MC if len(bytes_) < 17:
+        if len(bytes_) < 16:
             raise KNXcEMIException("Packet to short %d" % len(bytes_))
 
         self.pkt = bytes_
@@ -70,13 +71,15 @@ class KNXcEMI:
         #self.data   # 0x81 => write 1 / 0x80=> write 0 / 0x0 => read / 0x40 => response
 
     def check_sanity(self):
-        if self.header_lenght != 0x6 : raise KNXcEMIException("Wrong header size")
-        if self.version     != 0x10: raise KNXcEMIException("Wrong version")
-        if self.service     != bytearray([0x05,0x30]): raise KNXcEMIException("Wrong service")
-        if self.msg_code    != 0x29 : raise KNXcEMIException("Wrong msg_code")
-        if self.ctr_field1  != 0xbc : raise KNXcEMIException("Wrong ctr_field1")
-        if self.ctr_field2 not in [0xe0,0xd0,0xc0]: raise KNXcEMIException("Wrong ctr_field2 0x%x" % self.ctr_field2)
-        #if self.npdu_lenght != 0x01 : raise KNXcEMIException("Wrong npdu_lenght")
+        if self.header_lenght != 0x06 : raise KNXcEMIException("Wrong header size 0x%x" % self.header_lenght)
+        if self.version     != 0x10: raise KNXcEMIException("Wrong version 0x%x" % self.version)
+        if self.service     != bytearray([0x05,0x30]): raise KNXcEMIException("Wrong service 0x%x 0x%x" % self.service[0] % self.service[1])
+        if self.msg_code    != 0x29 : raise KNXcEMIException("Wrong msg_code 0x%x" % self.msg_code)
+        if self.ctr_field1 not in [0xbc,0xb0] : raise KNXcEMIException("Wrong ctr_field1 0x%x" % self.ctr_field1)
+        # JKX: ctr_field2 shoub in [0xe0,0xd0,0xc0] but Mael fix that to: 
+        if self.ctr_field2 not in [0xe0,0xd0,0xc0,0xb0,0x40,0x50]: raise KNXcEMIException("Wrong ctr_field2 0x%x" % self.ctr_field2)
+        # JKX : how could this arrive ? 
+        #if self.npdu_lenght != 0x01 : raise KNXcEMIException("Wrong npdu_lenght 0x%x" % self.npdu_lenght)
 
     @property
     def total_lenght(self):
diff --git a/devices/protocols/ZWave/README.rst b/devices/protocols/ZWave/README.rst
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f89279c53cad5ac2fd3c07f5496bd37250efd9af 100644
--- a/devices/protocols/ZWave/README.rst
+++ b/devices/protocols/ZWave/README.rst
@@ -0,0 +1,18 @@
+xAAL Zwave Gateway
+==================
+
+Install & Config
+----------------
+- Install the gateway as usual, python setup.py develop (or install)
+- Plug the Zstick
+- Run the gateway w/ python -m xaal.zwave
+- Change the serial port in the config file xaal.zwave.ini if needed.
+- The gateway will detect all paired products with the Zstick so, no
+  addtionnal config is needed
+
+Products
+--------
+- Supported products are in products/, feel free to add (and submit)
+  your own devices.
+  
+  
diff --git a/devices/protocols/ZWave/doc/Z-Stick_2E_manual_-_Aeotec_2.pdf b/devices/protocols/ZWave/doc/Z-Stick_2E_manual_-_Aeotec_2.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..619bfcd386e986e884d44ca3f540053140dc2770
Binary files /dev/null and b/devices/protocols/ZWave/doc/Z-Stick_2E_manual_-_Aeotec_2.pdf differ
diff --git a/devices/protocols/ZWave/xaal/zwave/debug.py b/devices/protocols/ZWave/xaal/zwave/debug.py
new file mode 100644
index 0000000000000000000000000000000000000000..f17a4c0704b076fd3db27809c40c815248396dcc
--- /dev/null
+++ b/devices/protocols/ZWave/xaal/zwave/debug.py
@@ -0,0 +1,7 @@
+from xaal.lib import Engine
+from . import gw
+
+eng = Engine()
+zw = gw.GW(eng)
+import pdb;pdb.set_trace()
+
diff --git a/devices/protocols/ZWave/xaal/zwave/gw.py b/devices/protocols/ZWave/xaal/zwave/gw.py
index 568646db6d03b4fa2a5ead0053b3b9b0e6d18967..5d7c2c5e85bbb51f668f6f7241f58d3c12cb3081 100644
--- a/devices/protocols/ZWave/xaal/zwave/gw.py
+++ b/devices/protocols/ZWave/xaal/zwave/gw.py
@@ -161,5 +161,6 @@ class GW(object):
 def setup(eng):
     try:
         gw=GW(eng)
+        return True
     except ZWaveException as err:
         logger.warning('Error w/ Zwave network: %s' % err.value)
diff --git a/devices/protocols/ZWave/xaal/zwave/products/Aeotec/ZW100.py b/devices/protocols/ZWave/xaal/zwave/products/Aeotec/ZW100.py
index 468c63644c71ba2affc7e12147412e95ad33a7ca..9f57b7d50143062b285d647f3f7294a0d4bc97db 100644
--- a/devices/protocols/ZWave/xaal/zwave/products/Aeotec/ZW100.py
+++ b/devices/protocols/ZWave/xaal/zwave/products/Aeotec/ZW100.py
@@ -16,11 +16,11 @@ class ZW100(core.ZDevice):
         dev.new_attribute('humidity')
         # luxmeter
         dev = self.new_device("luxmeter.basic")
-        dev.new_attribute('lux')
+        dev.new_attribute('illuminance')
         dev.new_attribute('ultraviolet')
         # motion sensor
         dev = self.new_device("motion.basic")
-        dev.new_attribute("motion")
+        dev.new_attribute("presence")
         # shock sensor
         dev = self.new_device("shock.basic")
         dev.new_attribute("shock")
@@ -45,17 +45,17 @@ class ZW100(core.ZDevice):
             self.devices[1].attributes['humidity'] = round(value.data)
         # luxmeter
         if value == self.get_value('lux'):
-            self.devices[2].attributes['lux'] = round(value.data)
+            self.devices[2].attributes['illuminance'] = round(value.data)
         if value == self.get_value('ultraviolet'):
             self.devices[2].attributes['ultraviolet'] = round(value.data)
         # motion & shock
         if value == self.get_value('burglar'):
             if value.data == 8:
-                self.devices[3].attributes['motion'] = True
+                self.devices[3].attributes['presence'] = True
             if value.data == 3:
                 self.devices[4].attributes['shock'] = True
             if value.data == 0:
-                self.devices[3].attributes['motion'] = False
+                self.devices[3].attributes['presence'] = False
                 self.devices[4].attributes['shock']  = False
         # battery
         if value == self.get_value('battery'):
diff --git a/devices/protocols/ZWave/xaal/zwave/products/Zipato/RGBBulb.py b/devices/protocols/ZWave/xaal/zwave/products/Zipato/RGBBulb.py
index 6727c3838fe60cf67f6cfa82e9354ca4f12d198f..60bbc417e435251369fbcccc75495bd8e0349233 100644
--- a/devices/protocols/ZWave/xaal/zwave/products/Zipato/RGBBulb.py
+++ b/devices/protocols/ZWave/xaal/zwave/products/Zipato/RGBBulb.py
@@ -14,7 +14,10 @@ class RGBBulb(core.ZDevice):
         lamp.add_method('on',self.on)
         lamp.add_method('off',self.off)
         lamp.add_method('dim',self.dim)
+        lamp.add_method('blink',self.blink)
         self.monitor_value('level',core.COMMAND_CLASS.SWITCH_MULTILEVEL)
+        self.monitor_value('color',core.COMMAND_CLASS.ZIP_ADV_SERVER,1)
+        self._blink_color = 0
 
     def set_level(self,value):
         self.set_value('level',value)
@@ -26,9 +29,36 @@ class RGBBulb(core.ZDevice):
     def off(self):
         self.set_level(0)
 
-    def dim(self,value):
-        if (value > 0) and (value <100):
-            self.set_level(value)
+    def dim(self,_value):
+        val = int(_value)
+        if (val > 0) and (val <100):
+            self.set_level(val)
+
+    def red(self):
+        self.get_value('color').data = '#FF00000000'
+
+    def white(self):
+        self.get_value('color').data = '#000000FFFF'
+        
+    def _blink(self):
+        # turn on, but avoid the timer..
+        if self._blink_color == 0:
+            self.red()
+            self._blink_color = 1
+        else:
+            self.white()
+            self._blink_color = 0
+        
+    def blink(self):
+        eng = self.gw.engine
+        state = self.devices[0].attributes["light"]
+        #self.set_value('level',0x63)
+        self.on()
+        eng.add_timer(self.white,19,1)        
+        if state == False:
+            eng.add_timer(self.off,20,1)
+        self.gw.engine.add_timer(self._blink,1,15)
+        
 
     def handle_value_changed(self,value):
         if value == self.get_value('level'):
@@ -38,3 +68,4 @@ class RGBBulb(core.ZDevice):
                 dev.attributes["light"] = False
             else:
                 dev.attributes["light"] = True
+                
diff --git a/devices/protocols/ZWave/xaal/zwave/test_gw.py b/devices/protocols/ZWave/xaal/zwave/test_gw.py
index 91ea3f84a34eabb39c7f9363167800fc15f3dfd2..2586feda151cb173f843ee361aa0c35b1eef4189 100644
--- a/devices/protocols/ZWave/xaal/zwave/test_gw.py
+++ b/devices/protocols/ZWave/xaal/zwave/test_gw.py
@@ -10,8 +10,8 @@ from pydispatch import dispatcher
 import sys
 import time
 
-from cmdclass import COMMAND_CLASS
-import auto
+from .cmdclass import COMMAND_CLASS
+#import auto
 
 #device="/dev/ttyACM0"
 device="/dev/ttyUSB0"
diff --git a/libs/lib/xaal/lib/core.py b/libs/lib/xaal/lib/core.py
index 12aeba38d10d813c35cd49566488a0c1ab86188d..1b84b912fec716a88e1007377d2a7d81b5592213 100644
--- a/libs/lib/xaal/lib/core.py
+++ b/libs/lib/xaal/lib/core.py
@@ -259,13 +259,13 @@ class Engine(object):
     #####################################################
     # timers
     #####################################################
-    def add_timer(self,func,period,repeat=-1):
+    def add_timer(self,func,period,counter=-1):
         """ 
         func: function to call
         period: period in second
-        repeat: number of repeat, -1 => always
+        counter: number of repeat, -1 => always
         """
-        t = Timer(func,period,repeat)
+        t = Timer(func,period,counter)
         self.timers.append(t)
         return t
 
@@ -287,9 +287,9 @@ class Engine(object):
                         t.func()
                     except CallbackError as e:
                         logger.error(e.description)
-                    if (t.repeat != -1):
-                        t.repeat = t.repeat-1
-                        if t.repeat == 0:
+                    if (t.counter != -1):
+                        t.counter = t.counter-1
+                        if t.counter == 0:
                             expire_list.append(t)
                     t.deadline = now + t.period
             # delete expired timers
@@ -414,9 +414,9 @@ def get_args_method(method):
 
 
 class Timer(object):
-    def __init__(self,func,period,repeat):
+    def __init__(self,func,period,counter):
         self.func = func
         self.period = period
-        self.repeat = repeat
-        self.deadline = 0
+        self.counter = counter
+        self.deadline = time.time() + period
         
diff --git a/scripts/btn_relay.py b/scripts/btn_relay.py
index aaf9ef139943832828a885ff2ccf44778df819ab..488b4d7f85bafe8587a2f12ececaf75689f0e89d 100644
--- a/scripts/btn_relay.py
+++ b/scripts/btn_relay.py
@@ -11,6 +11,13 @@ BTN1 = 'ec069c08-92af-11e8-80cd-408d5c18c800'
 BTN2 = '6fa87ef2-9975-11e8-b1fa-82ed25e6aa00'
 BTN3 = '821c6026-92ae-11e8-82af-408d5c18c800'
 
+BTN1 = '63b5ece6-c266-11e8-a0fc-400074bcb601'
+BTN4 = '63b5ece6-c266-11e8-a0fc-400074bcb605'
+BTN5 = 'c38e3f04-92b1-11e8-85ee-408d5c18c800'
+BTN3 = '6fa87ef2-9975-11e8-b1fa-82ed25e6aa00'
+
+RGB1 = 'b97c687c-d700-11e8-b0df-408d5c18c8f7'
+
 dev = None
 
 def send(targets,action,body=None):
@@ -18,22 +25,42 @@ def send(targets,action,body=None):
     engine = dev.engine
     engine.send_request(dev,targets,action,body)
 
+def rand_color_code():
+    import random
+    r = random.randint(0,255)
+    g = random.randint(0,255)
+    b = random.randint(0,255)
+    color='#%x%x%x' % (r,g,b)
+    return color
+
 
 def handle_msg(msg):
     if not msg.is_notify():
         return
     # search for the buttons 
+    """
     if msg.action == 'click':
-        if msg.source == BTN2:
+        if msg.source == BTN4:
             send([REL1,REL2],'toggle')
-        if msg.source == BTN1:
+        if msg.source in [BTN1,BTN5]:
             send([REL1],'toggle')
         if msg.source == BTN3:
-            send([REL2,],'toggle')            
-    if msg.action == 'double_click':
-        if msg.source in [BTN1,BTN3]:
-            send([REL1,REL2],'off')
+            send([REL2,],'toggle')
+    """
+    if msg.action == 'click':
+        send([RGB1,],'toggle')
+
+    if msg.action == 'click':
+        if msg.source in [BTN1,BTN3,BTN5]:
+            #send([REL1,REL2],'toggle')
+            #send([RGB1,],'setWhite',{'target':'5000'})
+            send([RGB1,],'toggle')
+
+        if msg.source == '6fa87ef2-9975-11e8-b1fa-82ed25e6aa01':
+            send([RGB1,],'setRGB',{'target':rand_color_code()})
 
+        if msg.source == '6fa87ef2-9975-11e8-b1fa-82ed25e6aa02':
+            send([RGB1,],'off')
 
 def main():
     global dev
diff --git a/scripts/ensibs_alarm_SDB_haut.py b/scripts/ensibs_alarm_SDB_haut.py
new file mode 100644
index 0000000000000000000000000000000000000000..5c5d3fdd160bf35203406d799f5b91c7fe676a8b
--- /dev/null
+++ b/scripts/ensibs_alarm_SDB_haut.py
@@ -0,0 +1,162 @@
+from xaal.lib import Device,Engine,tools,Message,helpers
+from xaal.monitor import Monitor,Notification
+import platform
+import time
+import logging
+from enum import Enum
+
+
+DELAY = 30
+
+ADDR     = 'aa4d1cbc-92af-11e8-80cd-408d5c18c801'
+PKG_NAME = 'scenario_ensibs_alerte'
+
+DOOR     = 'ce91c3a6-20b1-11e9-a250-a4badbf92500'
+MVT      = '93e09033-708e-11e8-956e-00fec8f7138c'
+LIGHTS   = ['93e09007-708e-11e8-956e-00fec8f7138c','93e09008-708e-11e8-956e-00fec8f7138c']
+
+BULLET   = ['6eb64b73-6e51-11e9-8f96-00fec8f7138c']
+BLINKS   = ['aa8cd2e4-8c5d-11e9-b0ba-b827ebe99201','980a639c-20b1-11e9-8d70-a4badbf92500']
+SIREN    = ['980a639c-20b1-11e9-8d70-a4badbf92501',]
+
+
+MONITORING_DEVICES = [DOOR,LIGHTS,MVT]
+
+class States(Enum):
+    free       = 'free'
+    busy       = 'busy'
+    fail       = 'fail'
+    no_motion  = 'no_motion'
+    alarm      = 'alarm'
+
+
+class Devices:
+    def __init__(self):
+        self.door     = None
+        self.light0    = None
+        self.light1    = None        
+        self.motion   = None
+
+    @property
+    def list(self):
+        return [self.door,self.light0,self.light1,self.motion]
+
+    def check(self):
+        for k in self.list:
+            if k == None: return False
+            if len(k.attributes.keys()) == 0: return False
+        return True
+    
+    def used(self,dev):
+        for k in self.list:
+            if k==dev: return True
+        return False
+
+logger = logging.getLogger(PKG_NAME)
+device = None
+devices = Devices()
+state = States.fail
+motion_timer = 0 
+
+def send(targets,action,body=None):
+    global device
+    device.engine.send_request(device,targets,action,body)
+
+def alert():
+    logger.warning('WARNING !!!!')
+    send(BULLET,'notify',{'title':'Alarme SDB haut !!','msg':"Personne inerte ou lumière oubliée"})
+    send(BLINKS,'blink')
+    send(SIREN,'play')
+
+
+def update_state():
+    global state,device
+    device.attributes['state'] = state.value
+
+
+def is_light():
+    if devices.light0.attributes['light']: return True
+    if devices.light1.attributes['light']: return True
+    return False
+
+def on_event(event,dev):
+    global state,motion_timer
+    if event == Notification.new_device:
+        if dev.address == DOOR  : devices.door   = dev
+        if dev.address == MVT   : devices.motion = dev
+        if dev.address == LIGHTS[0] : devices.light0  = dev
+        if dev.address == LIGHTS[1] : devices.light1  = dev
+
+        
+    if event == Notification.attribute_change:
+        if devices.check() == False:
+            state = States.fail
+            update_state()
+            return
+
+        if state == States.fail:
+            state = States.free
+            update_state()
+
+        logger.info(dev.attributes)
+        if dev == devices.door:
+            # close the door
+            if dev.attributes['position'] == False:
+                # mvt + light => busy 
+                if state == States.free and devices.motion.attributes['presence'] == True and is_light() == True:
+                    state = States.busy
+                # no light => free
+                if is_light() == False:
+                    state = States.free
+            else:
+                # somebody open the door
+                if state in [States.busy,States.alarm]:
+                    state = States.free
+
+        if dev == devices.motion:
+            # no motion while busy => start timer
+            if dev.attributes['presence']==False and state == States.busy:
+                motion_timer = time.time()
+                state = States.no_motion
+            # motion while state no_motion => just busy
+            if dev.attributes['presence'] == True and state == States.no_motion:
+                state = States.busy
+        update_state()
+
+
+def update():
+    global state,motion_timer,device
+    now = time.time()
+    if state == States.no_motion:
+        if now > (motion_timer + DELAY):
+            logger.warning('ALARME !!!')
+            alert()
+            state = States.alarm
+            device.attributes['state'] = state.value
+
+
+def filter_msg(msg):
+    if msg.source in MONITORING_DEVICES:
+        return True
+    return False
+
+
+def main():
+    global mon,device
+    device = Device('scenario.basic',ADDR)
+    device.new_attribute('state')
+    device.info = '%s@%s' % (PKG_NAME,platform.node())
+    engine = Engine()
+    engine.add_device(device)
+    engine.add_timer(update,1)
+    mon = Monitor(device,filter_func = filter_msg)
+    mon.subscribe(on_event)
+    engine.run()
+
+if __name__ == '__main__':
+    try:
+        helpers.setup_console_logger()
+        main()
+    except KeyboardInterrupt:
+        print('Bye bye')
+        
diff --git a/scripts/ensibs_alarm_WC_haut.py b/scripts/ensibs_alarm_WC_haut.py
new file mode 100644
index 0000000000000000000000000000000000000000..054392eae78bef5c0f7e9499dc79bfbbc7867e3a
--- /dev/null
+++ b/scripts/ensibs_alarm_WC_haut.py
@@ -0,0 +1,154 @@
+from xaal.lib import Device,Engine,tools,Message,helpers
+from xaal.monitor import Monitor,Notification
+import platform
+import time
+import logging
+from enum import Enum
+
+
+DELAY = 30
+
+ADDR = 'aa4d1cbc-92af-11e8-80cd-408d5c18c800'
+PKG_NAME = 'scenario_ensibs_alerte'
+
+DOOR   = 'cbdb198c-20b1-11e9-a250-a4badbf92500'
+MVT    = '93e09031-708e-11e8-956e-00fec8f7138c'
+LIGHT  = '93e09005-708e-11e8-956e-00fec8f7138c'
+
+BULLET= ['6eb64b73-6e51-11e9-8f96-00fec8f7138c']
+BLINKS = ['aa8cd2e4-8c5d-11e9-b0ba-b827ebe99201','980a639c-20b1-11e9-8d70-a4badbf92500']
+SIREN = ['980a639c-20b1-11e9-8d70-a4badbf92501',]
+
+
+MONITORING_DEVICES = [DOOR,LIGHT,MVT]
+
+class States(Enum):
+    free       = 'free'
+    busy       = 'busy'
+    fail       = 'fail'
+    no_motion  = 'no_motion'
+    alarm      = 'alarm'
+
+
+class Devices:
+    def __init__(self):
+        self.door = None
+        self.light = None
+        self.motion = None
+
+    @property
+    def list(self):
+        return [self.door,self.light,self.motion]
+
+    def check(self):
+        for k in self.list:
+            if k == None: return False
+            if len(k.attributes.keys()) == 0: return False
+        return True
+    
+    def used(self,dev):
+        for k in self.list:
+            if k==dev: return True
+        return False
+
+logger = logging.getLogger(PKG_NAME)
+device = None
+devices = Devices()
+state = States.fail
+motion_timer = 0 
+
+def send(targets,action,body=None):
+    global device
+    device.engine.send_request(device,targets,action,body)
+
+def alert():
+    logger.warning('WARNING !!!!')
+    send(BULLET,'notify',{'title':'Alarme WC haut !!','msg':"Personne inerte ou lumière oubliée"})
+    send(BLINKS,'blink')
+    send(SIREN,'play')
+
+
+def update_state():
+    global state,device
+    device.attributes['state'] = state.value
+
+
+def on_event(event,dev):
+    global state,motion_timer
+    if event == Notification.new_device:
+        if dev.address == DOOR: devices.door   = dev
+        if dev.address == MVT : devices.motion = dev
+        if dev.address == LIGHT: devices.light = dev
+
+    if event == Notification.attribute_change:
+        if devices.check() == False:
+            state = States.fail
+            update_state()
+            return
+
+        if state == States.fail:
+            state = States.free
+            update_state()
+
+        logger.info(dev.attributes)
+        if dev == devices.door:
+            # close the door
+            if dev.attributes['position'] == False:
+                # mvt + light => busy 
+                if state == States.free and devices.motion.attributes['presence'] == True and devices.light.attributes['light'] == True:
+                    state = States.busy
+                # no light => free
+                if devices.light.attributes['light'] == False:
+                    state = States.free
+            else:
+                # somebody open the door
+                if state in [States.busy,States.alarm]:
+                    state = States.free
+
+        if dev == devices.motion:
+            # no motion while busy => start timer
+            if dev.attributes['presence']==False and state == States.busy:
+                motion_timer = time.time()
+                state = States.no_motion
+            # motion while state no_motion => just busy
+            if dev.attributes['presence'] == True and state == States.no_motion:
+                state = States.busy
+        update_state()
+
+
+def update():
+    global state,motion_timer,device
+    now = time.time()
+    if state == States.no_motion:
+        if now > (motion_timer + DELAY):
+            logger.warning('ALARME !!!')
+            alert()
+            state = States.alarm
+            device.attributes['state'] = state.value
+
+
+def filter_msg(msg):
+    if msg.source in MONITORING_DEVICES:
+        return True
+    return False
+
+
+def main():
+    global mon,device
+    device = Device('scenario.basic',ADDR)
+    device.new_attribute('state')
+    device.info = '%s@%s' % (PKG_NAME,platform.node())
+    engine = Engine()
+    engine.add_device(device)
+    engine.add_timer(update,1)
+    mon = Monitor(device,filter_func = filter_msg)
+    mon.subscribe(on_event)
+    engine.run()
+
+if __name__ == '__main__':
+    try:
+        helpers.setup_console_logger()
+        main()
+    except KeyboardInterrupt:
+        print('Bye bye')
+        
diff --git a/scripts/ensibs_btn.py b/scripts/ensibs_btn.py
new file mode 100644
index 0000000000000000000000000000000000000000..a566758b506f890c82bc806c64fac60a980ee43b
--- /dev/null
+++ b/scripts/ensibs_btn.py
@@ -0,0 +1,113 @@
+from xaal.lib import Engine
+from xaal.schemas import devices
+from xaal.monitor import Monitor
+import platform
+
+PKG_NAME = 'scenario_btn_ensibs'
+
+LAMPS=['aa8cd2e4-8c5d-11e9-b0ba-b827ebe99201']
+
+# Edisio labo
+EDISIO=['43c06446-8c5c-11e9-a105-b80673742b01','43c06446-8c5c-11e9-a105-b80673742b03','43c06446-8c5c-11e9-a105-b80673742b05',
+        '43c06446-8c5c-11e9-a105-b80673742b07','43c06446-8c5c-11e9-a105-b80673742b08']
+
+# Aquara sw1
+AQUARA_1=['fb1f8648-20ba-11e9-b352-a4badbf92500','fb1f8648-20ba-11e9-b352-a4badbf92501','fb1f8648-20ba-11e9-b352-a4badbf92502']
+AQUARA_2=['00796898-20bb-11e9-b352-a4badbf92500','00796898-20bb-11e9-b352-a4badbf92501','00796898-20bb-11e9-b352-a4badbf92502']
+AQUARA_R= '1ec6bbd0-20b5-11e9-b352-a4badbf92500'
+
+SHUTERS=['e4b05165-be5d-46d5-acd0-4da7be1158ed','2fe70f46-3ece-44d1-af34-2d82e10fb854']
+
+SIREN = ['980a639c-20b1-11e9-8d70-a4badbf92501',]
+PUSH_BULLET=['bc5bb184-8d16-11e9-b4db-9cebe88e1963']
+
+LAMPS_A = [LAMPS[0]]
+
+BLINKS = ['aa8cd2e4-8c5d-11e9-b0ba-b827ebe99201','980a639c-20b1-11e9-8d70-a4badbf92500']
+
+RELAYS = ['d34fd5be-8c58-11e9-8999-b827ebe99201']
+
+mon = None
+dev = None
+
+def send(targets,action,body=None):
+    global dev
+    dev.engine.send_request(dev,targets,action,body)
+
+def search_for_light(lamps):
+    for l in lamps:
+        dev = mon.devices.get_with_addr(l)
+        if dev:
+            light = dev.attributes.get('light',None)
+            if light:
+                return True
+    return False
+
+def on_off_light(lamps):
+    print('on_off %s' % lamps)
+    if search_for_light(lamps):
+        send(lamps,'off')
+        return False
+    else:
+        send(lamps,'on')
+        return True
+
+def siren_play(snd=2):
+    send(SIREN,'play',{'sound':snd})
+
+def siren_stop():
+    send(SIREN,'stop')
+
+def pushbullet(title,msg):
+    send(PUSH_BULLET,'notify',{'title': title,'msg':msg})
+
+def blink():
+    send(BLINKS,'blink')
+
+
+def handle_msg(msg):
+    if not msg.is_notify():
+        return
+    # search for the buttons 
+    if msg.action == 'click':
+        if msg.source == AQUARA_R:
+            blink()
+            siren_play(2)
+            pushbullet('Alerte','')
+
+        if msg.source == AQUARA_1[0]:
+            #on_off_light(LAMPS_A)
+            send(RELAYS,'on')
+
+        if msg.source == AQUARA_1[1]:
+            #on_off_light(LAMPS_A)
+            send(RELAYS,'off')
+
+        if msg.source == AQUARA_2[0]: 
+            siren_play(20)
+
+        if msg.source == AQUARA_2[1]: 
+            pushbullet('Alerte','Intrusion')
+            siren_play(1)
+
+        if msg.source == AQUARA_2[2]:
+            siren_stop()
+
+            #send(SHUTERS,'stop')
+
+                
+def main():
+    global mon,dev
+    dev = devices.basic()
+    dev.info = '%s@%s' % (PKG_NAME,platform.node())
+    engine = Engine()
+    engine.add_device(dev)
+    engine.add_rx_handler(handle_msg)
+    mon = Monitor(dev)
+    engine.run()
+
+if __name__ == '__main__':
+    try:
+        main()
+    except KeyboardInterrupt:
+        print('Bye bye')