more improvements and fixes and new bugs
diff --git a/wally/sensors/storage/grafana.py b/wally/sensors/grafana.py
similarity index 100%
rename from wally/sensors/storage/grafana.py
rename to wally/sensors/grafana.py
diff --git a/wally/sensors/storage/influx_exporter.py b/wally/sensors/influx_exporter.py
similarity index 100%
rename from wally/sensors/storage/influx_exporter.py
rename to wally/sensors/influx_exporter.py
diff --git a/wally/sensors/main.py b/wally/sensors/main.py
index e86bbed..2b6ab8b 100644
--- a/wally/sensors/main.py
+++ b/wally/sensors/main.py
@@ -50,12 +50,12 @@
     sender = create_protocol(opts.url)
     prev = {}
 
-    while True:
-        try:
-            source_id = str(required_sensors.pop('source_id'))
-        except KeyError:
-            source_id = None
+    try:
+        source_id = str(required_sensors.pop('source_id'))
+    except KeyError:
+        source_id = None
 
+    while True:
         gtime, data = get_values(required_sensors.items())
         curr = {'time': SensorInfo(gtime, True)}
         for name, val in data.items():
diff --git a/wally/sensors/storage/__init__.py b/wally/sensors/storage/__init__.py
deleted file mode 100644
index d7bf6aa..0000000
--- a/wally/sensors/storage/__init__.py
+++ /dev/null
@@ -1,104 +0,0 @@
-import struct
-
-
-def pack(val, tp=True):
-    if isinstance(val, int):
-        assert 0 <= val < 2 ** 16
-
-        if tp:
-            res = 'i'
-        else:
-            res = ""
-
-        res += struct.pack("!U", val)
-    elif isinstance(val, dict):
-        assert len(val) < 2 ** 16
-        if tp:
-            res = "d"
-        else:
-            res = ""
-
-        res += struct.pack("!U", len(val))
-        for k, v in dict.items():
-            assert 0 <= k < 2 ** 16
-            assert 0 <= v < 2 ** 32
-            res += struct.pack("!UI", k, v)
-    elif isinstance(val, str):
-        assert len(val) < 256
-        if tp:
-            res = "s"
-        else:
-            res = ""
-        res += chr(len(val)) + val
-    else:
-        raise ValueError()
-
-    return res
-
-
-def unpack(fd, tp=None):
-    if tp is None:
-        tp = fd.read(1)
-
-    if tp == 'i':
-        return struct.unpack("!U", fd.read(2))
-    elif tp == 'd':
-        res = {}
-        val_len = struct.unpack("!U", fd.read(2))
-        for _ in range(val_len):
-            k, v = struct.unpack("!UI", fd.read(6))
-            res[k] = v
-        return res
-    elif tp == 's':
-        val_len = struct.unpack("!U", fd.read(2))
-        return fd.read(val_len)
-
-    raise ValueError()
-
-
-class LocalStorage(object):
-    NEW_DATA = 0
-    NEW_SENSOR = 1
-    NEW_SOURCE = 2
-
-    def __init__(self, fd):
-        self.fd = fd
-        self.sensor_ids = {}
-        self.sources_ids = {}
-        self.max_source_id = 0
-        self.max_sensor_id = 0
-
-    def add_data(self, source, sensor_values):
-        source_id = self.sources_ids.get(source)
-        if source_id is None:
-            source_id = self.max_source_id
-            self.sources_ids[source] = source_id
-            self.emit(self.NEW_SOURCE, source_id, source)
-            self.max_source_id += 1
-
-        new_sensor_values = {}
-
-        for name, val in sensor_values.items():
-            sensor_id = self.sensor_ids.get(name)
-            if sensor_id is None:
-                sensor_id = self.max_sensor_id
-                self.sensor_ids[name] = sensor_id
-                self.emit(self.NEW_SENSOR, sensor_id, name)
-                self.max_sensor_id += 1
-            new_sensor_values[sensor_id] = val
-
-        self.emit(self.NEW_DATA, source_id, new_sensor_values)
-
-    def emit(self, tp, v1, v2):
-        self.fd.write(chr(tp) + pack(v1, False) + pack(v2))
-
-    def readall(self):
-        tp = self.fd.read(1)
-        if ord(tp) == self.NEW_DATA:
-            pass
-        elif ord(tp) == self.NEW_SENSOR:
-            pass
-        elif ord(tp) == self.NEW_SOURCE:
-            pass
-        else:
-            raise ValueError()
diff --git a/wally/sensors/storage/grafana_template.js b/wally/sensors/storage/grafana_template.js
deleted file mode 100644
index 7c57924..0000000
--- a/wally/sensors/storage/grafana_template.js
+++ /dev/null
@@ -1,46 +0,0 @@
-/* global _ */
-
-/*
- * Complex scripted dashboard
- * This script generates a dashboard object that Grafana can load. It also takes a number of user
- * supplied URL parameters (int ARGS variable)
- *
- * Return a dashboard object, or a function
- *
- * For async scripts, return a function, this function must take a single callback function as argument,
- * call this callback function with the dashboard object (look at scripted_async.js for an example)
- */
-
-
-
-// accessable variables in this scope
-var window, document, ARGS, $, jQuery, moment, kbn;
-
-// Setup some variables
-var dashboard;
-
-// All url parameters are available via the ARGS object
-var ARGS;
-
-// Intialize a skeleton with nothing but a rows array and service object
-dashboard = {rows : []};
-
-// Set a title
-dashboard.title = 'Tests dash';
-
-// Set default time
-// time can be overriden in the url using from/to parameteres, but this is
-// handled automatically in grafana core during dashboard initialization
-dashboard.time = {
-    from: "now-5m",
-    to: "now"
-};
-
-dashboard.rows.push({
-    title: 'Chart',
-    height: '300px',
-    panels: %s
-});
-
-
-return dashboard;
diff --git a/wally/sensors/storage/koder.js b/wally/sensors/storage/koder.js
deleted file mode 100644
index a65a454..0000000
--- a/wally/sensors/storage/koder.js
+++ /dev/null
@@ -1,47 +0,0 @@
-/* global _ */
-
-/*
- * Complex scripted dashboard
- * This script generates a dashboard object that Grafana can load. It also takes a number of user
- * supplied URL parameters (int ARGS variable)
- *
- * Return a dashboard object, or a function
- *
- * For async scripts, return a function, this function must take a single callback function as argument,
- * call this callback function with the dashboard object (look at scripted_async.js for an example)
- */
-
-
-
-// accessable variables in this scope
-var window, document, ARGS, $, jQuery, moment, kbn;
-
-// Setup some variables
-var dashboard;
-
-// All url parameters are available via the ARGS object
-var ARGS;
-
-// Intialize a skeleton with nothing but a rows array and service object
-dashboard = {rows : []};
-
-// Set a title
-dashboard.title = 'Tests dash';
-
-// Set default time
-// time can be overriden in the url using from/to parameteres, but this is
-// handled automatically in grafana core during dashboard initialization
-dashboard.time = {
-    from: "now-5m",
-    to: "now"
-};
-
-dashboard.rows.push({
-    title: 'Chart',
-    height: '300px',
-    panels: [{"span": 12, "title": "writes_completed", "linewidth": 2, "type": "graph", "targets": [{"alias": "192.168.0.104 io sda1", "interval": "", "target": "disk io", "rawQuery": true, "query": "select value from \"writes_completed\" where $timeFilter and host='192.168.0.104' and device='sda1' order asc"}, {"alias": "192.168.0.104 io rbd1", "interval": "", "target": "disk io", "rawQuery": true, "query": "select value from \"writes_completed\" where $timeFilter and host='192.168.0.104' and device='rbd1' order asc"}], "tooltip": {"shared": true}, "fill": 1}, {"span": 12, "title": "sectors_written", "linewidth": 2, "type": "graph", "targets": [{"alias": "192.168.0.104 io sda1", "interval": "", "target": "disk io", "rawQuery": true, "query": "select value from \"sectors_written\" where $timeFilter and host='192.168.0.104' and device='sda1' order asc"}, {"alias": "192.168.0.104 io rbd1", "interval": "", "target": "disk io", "rawQuery": true, "query": "select value from \"sectors_written\" where $timeFilter and host='192.168.0.104' and device='rbd1' order asc"}], "tooltip": {"shared": true}, "fill": 1}]
-});
-
-
-return dashboard;
-