diff --git a/ekgplotter/ekgplotter/__init__.py b/ekgplotter/ekgplotter/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/ekgplotter/ekgplotter/main.py b/ekgplotter/ekgplotter/main.py
new file mode 100644
index 0000000..247e02a
--- /dev/null
+++ b/ekgplotter/ekgplotter/main.py
@@ -0,0 +1,151 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+
+from __future__ import absolute_import
+
+
+import pyqtgraph as pg
+import select
+import socket
+import cStringIO
+import subprocess
+import threading
+import time
+from PyQt4.QtCore import QBuffer, QByteArray, QIODevice
+
+from collections import deque
+
+
+"""This module implements the standalone filtering tool in the chaosc framework.
+
+It uses the chaosc osc_lib but does not depend on chaosc features, so it can
+be used with other osc compatible gear.
+
+We provide here osc message filtering based on python regex defined in a file
+and a very flexible transcoding toolchain, but it's up to your python skills
+to master them. The TranscoderBaseHandler subclasses should be defined in the
+appropriate python module you place in the config directory. Please refer for
+a howto/examples to our comprehensive docs or look into the provided example
+transcoding.py file.
+"""
+
+# This file is part of chaosc
+#
+# chaosc is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# chaosc is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with chaosc. If not, see .
+#
+# Copyright (C) 2012-2014 Stefan Kögl
+
+
+import atexit
+import sys, argparse
+
+from datetime import datetime
+from chaosc.simpleOSCServer import SimpleOSCServer
+import chaosc._version
+
+
+class ChaoscLogger(SimpleOSCServer):
+ """OSC filtering/transcoding middleware
+ """
+
+ def __init__(self, args):
+ """ctor for filter server
+
+ starts the server, loads scene filters and transcoders and chooses
+ the request handler, which is one of
+ forward only, forward and dump, dump only.
+
+ :param result: return value of argparse.parse_args
+ :type result: namespace object
+ """
+
+ d = datetime.now().strftime("%x %X")
+ print "%s: starting up chaosc_dump-%s..." % (d, chaosc._version.__version__)
+ SimpleOSCServer.__init__(self, (args.own_host, args.own_port))
+ self.args = args
+ self.chaosc_address = (args.chaosc_host, args.chaosc_port)
+
+ if args.subscribe:
+ self.subscribe_me(self.chaosc_address, (args.own_host, args.own_port),
+ args.token, args.subscriber_label)
+
+ self.plot_data = deque([0] * 100)
+ self.plt = pg.plot()
+
+
+ def dispatchMessage(self, osc_address, typetags, args, packet,
+ client_address):
+ """Handles this filtering, transcoding steps and forwards the result
+
+ :param osc_address: the OSC address string.
+ :type osc_address: str
+
+ :param typetags: the typetags of args
+ :type typetags: list
+
+ :param args: the osc message args
+ :type args: list
+
+ :param packet: the binary representation of a osc message
+ :type packet: str
+
+ :param client_address: (host, port) of the requesting client
+ :type client_address: tuple
+ """
+
+
+ if osc_address == "/uwe/ekg":
+ self.plot_data.appendleft(args[0])
+ self.plot_data.pop()
+ self.plt.plot(self.plot_data, clear=True)
+ exporter = pg.exporters.ImageExporter.ImageExporter(self.plt.plotItem)
+ exporter.parameters()['width'] = 1024
+ name = '/tmp/plotImage.jpg'
+ exporter.export(name)
+
+
+
+ def unsubscribe(self):
+ self.unsubscribe_me(self.chaosc_address, (self.args.own_host, self.args.own_port),
+ self.args.token)
+
+
+
+def main():
+ parser = argparse.ArgumentParser(prog='ekgplotter')
+ main_args_group = parser.add_argument_group('main flags', 'flags for chaosc_transcoder')
+ chaosc_args_group = parser.add_argument_group('chaosc', 'flags relevant for interacting with chaosc')
+
+ main_args_group.add_argument('-o', "--own_host", required=True,
+ type=str, help='my host')
+ main_args_group.add_argument('-p', "--own_port", required=True,
+ type=int, help='my port')
+
+ chaosc_args_group.add_argument('-s', '--subscribe', action="store_true",
+ help='if True, this transcoder subscribes itself to chaosc. If you use this, you need to provide more flags in this group')
+ chaosc_args_group.add_argument('-S', '--subscriber_label', type=str, default="chaosc_transcoder",
+ help='the string to use for subscription label, default="chaosc_transcoder"')
+ chaosc_args_group.add_argument('-t', '--token', type=str, default="sekret",
+ help='token to authorize subscription command, default="sekret"')
+ chaosc_args_group.add_argument("-H", '--chaosc_host',
+ type=str, help='host of chaosc instance')
+ chaosc_args_group.add_argument("-P", '--chaosc_port',
+ type=int, help='port of chaosc instance')
+
+ server = ChaoscLogger(parser.parse_args(sys.argv[1:]))
+
+ atexit.register(server.unsubscribe)
+ server.serve_forever()
+
diff --git a/ekgplotter/setup.py b/ekgplotter/setup.py
new file mode 100644
index 0000000..2d45c49
--- /dev/null
+++ b/ekgplotter/setup.py
@@ -0,0 +1,55 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+from distribute_setup import use_setuptools
+use_setuptools()
+
+import sys
+from setuptools import find_packages, setup
+
+if sys.version_info >= (3,):
+ extras['use_2to3'] = True
+
+setup(
+ name='ekgplotter',
+ version="0.1",
+ packages=find_packages(exclude=["scripts",]),
+
+ include_package_data = True,
+
+ package_data = {
+ "chaosc" : ["config/*",]},
+
+ exclude_package_data = {'': ['.gitignore']},
+
+ install_requires=[],
+
+ # installing unzipped
+ zip_safe = False,
+
+ # predefined extension points, e.g. for plugins
+ entry_points = """
+ [console_scripts]
+ ekgplotter = ekgplotter.main:main
+ """,
+ # pypi metadata
+ author = "Stefan Kögl",
+
+ # FIXME: add author email
+ author_email = "",
+ description = "osc filtering application level gateway",
+
+ # FIXME: add long_description
+ long_description = """
+ """,
+
+ # FIXME: add license
+ license = "LGPL",
+
+ # FIXME: add keywords
+ keywords = "",
+
+ # FIXME: add download url
+ url = "",
+ test_suite='tests'
+)
diff --git a/sensors2osc/sensors2osc/sensorTest.py b/sensors2osc/sensors2osc/sensorTest.py
new file mode 100644
index 0000000..2fe385d
--- /dev/null
+++ b/sensors2osc/sensors2osc/sensorTest.py
@@ -0,0 +1,190 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# This file is part of chaosc
+#
+# chaosc is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# chaosc is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with chaosc. If not, see .
+#
+# Copyright (C) 2014 Stefan Kögl
+
+import argparse
+import os.path
+import select
+import serial
+import socket
+import sys
+import datetime
+
+try:
+ from chaosc.c_osc_lib import OSCMessage
+except ImportError as e:
+ print(e)
+ from chaosc.osc_lib import OSCMessage
+
+
+class Forwarder(object):
+ def __init__(self, actor, platform, device):
+ self.actor = actor
+ self.platform = platform
+ self.device = device
+ self.serial = serial.Serial()
+ self.serial.port = device
+ self.serial.baudrate = 115200
+ self.serial.timeout = 0
+ self.buf_ser2osc = ""
+
+ self.serial.open()
+
+ def close(self):
+ """Close all resources and unpublish service"""
+ print "%s: closing..." % (self.device, )
+ self.serial.close()
+
+
+class EHealth2OSC(Forwarder):
+ def __init__(self, actor, platform, device):
+ super(EHealth2OSC, self).__init__(actor, platform, device)
+
+ def handle_read(self, osc_sock):
+ data = self.serial.readline()[:-2]
+ print repr(data)
+ try:
+ airFlow, emg, temp = data.split(";")
+ except ValueError:
+ return
+ try:
+ airFlow = int(airFlow)
+ emg = int(emg)
+ temp = int(temp);
+ except ValueError:
+ return
+ osc_message = OSCMessage("/%s/airFlow" % self.actor)
+ osc_message.appendTypedArg(airFlow, "i")
+ osc_sock.sendall(osc_message.encode_osc())
+ osc_message = OSCMessage("/%s/emg" % self.actor)
+ osc_message.appendTypedArg(emg, "i")
+ osc_sock.sendall(osc_message.encode_osc())
+ osc_message = OSCMessage("/%s/temperatur" % self.actor)
+ osc_message.appendTypedArg(temp, "i")
+ osc_sock.sendall(osc_message.encode_osc())
+
+
+class EKG2OSC(Forwarder):
+ def __init__(self, actor, platform, device):
+ super(EKG2OSC, self).__init__(actor, platform, device)
+
+ def handle_read(self, osc_sock):
+ t = ord(self.serial.read(1))
+ osc_message = OSCMessage("/%s/ekg" % self.actor)
+ osc_message.appendTypedArg(t, "i")
+ osc_sock.sendall(osc_message.encode_osc())
+
+
+class RingBuffer(object):
+ def __init__(self, length):
+ self.length = length
+ self.ring_buf = [-1 for i in xrange(length)]
+ self.head = 0
+
+ def append(self, value):
+ self.ring_buf[self.head] = value
+ self.head = (self.head + 1) % self.length
+
+ def getData(self):
+ print "getData", self.ring_buf, self.head
+ data = list()
+ for i in range(7, 1, -1):
+ value = self.ring_buf[(self.head - i) % self.length]
+ if value == -1:
+ raise ValueError("not complete")
+ data.append(value)
+ if data[0] != 0x0 or data[1] != 0xff:
+ raise ValueError("not synced")
+ return data[2:]
+
+
+
+class Pulse2OSC(Forwarder):
+ def __init__(self, actor, platform, device):
+ super(Pulse2OSC, self).__init__(actor, platform, device)
+ self.buf = RingBuffer(6)
+ self.heartbeat_on = False
+
+ def handle_read(self, osc_sock):
+ t = ord(self.serial.read(1))
+ self.buf.append(t)
+
+ if t == 0:
+ try:
+ heart_signal, heart_rate, o2, pulse = self.buf.getData()
+
+ if pulse == 245 and not self.heartbeat_on:
+ osc_message = OSCMessage("/%s/heartbeat" % self.actor)
+ osc_message.appendTypedArg(1, "i")
+ osc_message.appendTypedArg(heart_rate, "i")
+ osc_message.appendTypedArg(o2, "i")
+ osc_sock.sendall(osc_message.encode_osc())
+ print "heartbeat", datetime.datetime.now(), heart_signal
+ self.heartbeat_on = True
+ elif pulse == 1 and self.heartbeat_on:
+ #print "off heartbeat", datetime.datetime.now(), heart_signal
+ self.heartbeat_on = False
+ osc_message = OSCMessage("/%s/heartbeat" % self.actor)
+ osc_message.appendTypedArg(0, "i")
+ osc_message.appendTypedArg(heart_rate, "i")
+ osc_message.appendTypedArg(o2, "i")
+ osc_sock.sendall(osc_message.encode_osc())
+ except ValueError, e:
+ print e
+
+
+def main():
+ parser = argparse.ArgumentParser(prog='psychose_actor')
+ parser.add_argument("-H", '--chaosc_host', required=True,
+ type=str, help='host of chaosc instance to control')
+ parser.add_argument("-p", '--chaosc_port', required=True,
+ type=int, help='port of chaosc instance to control')
+ parser.add_argument("-t", '--type', required=True,
+ type=str, help='ekg, pulse, ehealth')
+ parser.add_argument("-d", '--device', required=True,
+ type=str, help='device node under /dev')
+ parser.add_argument("-a", '--actor', required=True,
+ type=str, help='actor name')
+
+
+ args = parser.parse_args(sys.argv[1:])
+
+ osc_sock = socket.socket(2, 2, 17)
+ osc_sock.connect((args.chaosc_host, args.chaosc_port))
+
+ used_devices = dict()
+
+ actor = args.actor
+ if args.type == "ehealth":
+ used_devices[device] = EHealth2OSC(actor, "ehealth", args.device)
+ elif args.type == "ekg":
+ used_devices[device] = EKG2OSC(actor, "ekg", args.device)
+ elif args.type == "pulse":
+ used_devices[device] = Pulse2OSC(actor, "pulse", args.device)
+ else:
+ raise ValueError("unknown description %r for device %r" % (description, device))
+
+ while 1:
+ read_map = {}
+ for forwarder in used_devices.values():
+ read_map[forwarder.serial] = forwarder.handle_read
+
+ readers, writers, errors = select.select(read_map, [], [], 0.1)
+ for reader in readers:
+ read_map[reader](osc_sock)
diff --git a/sensors2osc/setup.py b/sensors2osc/setup.py
index 35806a6..b42ad6c 100644
--- a/sensors2osc/setup.py
+++ b/sensors2osc/setup.py
@@ -4,7 +4,6 @@
from distribute_setup import use_setuptools
use_setuptools()
-from scripts.version import get_git_version
import sys
from setuptools import find_packages, setup
@@ -33,6 +32,7 @@ setup(
entry_points = """
[console_scripts]
sensors2osc = sensors2osc.main:main
+ sensorTest = sensors2osc.sensorTest:main
""",
# pypi metadata
author = "Stefan Kögl",