diff --git a/ekgplotter/ekgplotter/ekg_plotter_unused.py b/ekgplotter/ekgplotter/ekg_plotter_unused.py
new file mode 100644
index 0000000..1cd2542
--- /dev/null
+++ b/ekgplotter/ekgplotter/ekg_plotter_unused.py
@@ -0,0 +1,169 @@
+import numpy as np
+import string,cgi,time, random, socket
+from os import curdir, sep
+from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
+from SocketServer import ThreadingMixIn, ForkingMixIn
+import select
+import re
+
+from collections import deque
+
+from PyQt4.QtCore import QBuffer, QByteArray, QIODevice
+from PyQt4 import QtGui
+import pyqtgraph as pg
+
+from pyqtgraph.widgets.PlotWidget import PlotWidget
+
+
+try:
+ from chaosc.c_osc_lib import decode_osc
+except ImportError as e:
+ print(e)
+ from chaosc.osc_lib import decode_osc
+
+QAPP = None
+
+def mkQApp():
+ if QtGui.QApplication.instance() is None:
+ global QAPP
+ QAPP = QtGui.QApplication([])
+
+
+class PlotWindow(PlotWidget):
+ def __init__(self, title=None, **kargs):
+ mkQApp()
+ self.win = QtGui.QMainWindow()
+ PlotWidget.__init__(self, **kargs)
+ self.win.setCentralWidget(self)
+ for m in ['resize']:
+ setattr(self, m, getattr(self.win, m))
+ if title is not None:
+ self.win.setWindowTitle(title)
+
+
+class MyHandler(BaseHTTPRequestHandler):
+ def do_GET(self):
+ print "get"
+ global plotValues
+ try:
+ self.path=re.sub('[^.a-zA-Z0-9]', "",str(self.path))
+ if self.path=="" or self.path==None or self.path[:1]==".":
+ return
+ if self.path.endswith(".html"):
+ f = open(curdir + sep + self.path)
+ self.send_response(200)
+ self.send_header('Content-type', 'text/html')
+ self.end_headers()
+ self.wfile.write(f.read())
+ f.close()
+ return
+ if self.path.endswith(".mjpeg"):
+ self.send_response(200)
+
+ plot_data1 = deque([0] * 100)
+ plot_data2 = deque([254/3] * 100)
+ plot_data3 = deque([254/3*2] * 100)
+ plt = PlotWindow(title="EKG", name="Merle")
+ plt.addLegend()
+ #plt = pg.plot(pen=(0, 3*1.3))
+ plt.resize(1280, 720)
+ plotItem1 = pg.PlotCurveItem(pen=(0, 3*1.3), name="bjoern")
+ plotItem2 = pg.PlotCurveItem(pen=(1, 3*1.3), name="merle")
+ plotItem3 = pg.PlotCurveItem(pen=(2, 3*1.3), name="uwe")
+ plotItem1.setPos(0, 0*6)
+ plotItem2.setPos(0, 1*6)
+ plotItem3.setPos(0, 2*6)
+ plt.addItem(plotItem1)
+ plt.addItem(plotItem2)
+ plt.addItem(plotItem3)
+
+ plt.setLabel('left', "EKG")
+ plt.setLabel('bottom', "Time")
+ plt.showGrid(True, True)
+ ba = plt.getAxis("bottom")
+ bl = plt.getAxis("left")
+ ba.setTicks([])
+ bl.setTicks([])
+ plt.setYRange(0, 254)
+ print type(plt)
+ self.wfile.write("Content-Type: multipart/x-mixed-replace; boundary=--aaboundary")
+ self.wfile.write("\r\n\r\n")
+ osc_sock = socket.socket(2, 2, 17)
+ osc_sock.bind(("", 10000))
+ osc_sock.setblocking(0)
+ last = time.time()
+ now = last
+
+ while 1:
+ for i in xrange(3):
+ reads, writes, errs = select.select([osc_sock], [], [], 0.01)
+ #print reads, writes, errs
+ if reads:
+ osc_input = reads[0].recv(4096)
+ osc_address, typetags, args = decode_osc(osc_input, 0, len(osc_input))
+ #print "osc", osc_address, typetags, args
+ if osc_address.startswith("/bjoern"):
+ plot_data1.appendleft(args[0] / 3)
+ plot_data1.pop()
+ elif osc_address.startswith("/merle"):
+ plot_data2.appendleft(args[0] / 3 + 254/3)
+ plot_data2.pop()
+ elif osc_address.startswith("/uwe"):
+ plot_data3.appendleft(args[0] / 3 + 254/3*2)
+ plot_data3.pop()
+
+ plotItem1.setData(y=np.array(plot_data1), clear=True)
+ plotItem2.setData(y=np.array(plot_data2), clear=True)
+ plotItem3.setData(y=np.array(plot_data3), clear=True)
+ #item = plt.plot(plot_data1, pen=(0, 3*1.3), clear=True)
+
+ exporter = pg.exporters.ImageExporter.ImageExporter(plt.plotItem)
+ exporter.parameters()['width'] = 1280
+ #exporter.parameters()['height'] = 720
+ name = 'tmpfile'
+ img = exporter.export(name, True)
+ buffer = QBuffer()
+ buffer.open(QIODevice.ReadWrite)
+ img.save(buffer, "JPG", 100)
+ JpegData = buffer.data()
+ self.wfile.write("--aaboundary\r\n")
+ self.wfile.write("Content-Type: image/jpeg\r\n")
+ self.wfile.write("Content-length: %d\r\n\r\n" % len(JpegData))
+ self.wfile.write(JpegData)
+ self.wfile.write("\r\n\r\n\r\n")
+ now = time.time()
+ dur = now - last
+ print dur
+ wait = 0.04 - dur
+ if wait > 0:
+ time.sleep(wait)
+ last = now
+ return
+ if self.path.endswith(".jpeg"):
+ f = open(curdir + sep + self.path)
+ self.send_response(200)
+ self.send_header('Content-type','image/jpeg')
+ self.end_headers()
+ self.wfile.write(f.read())
+ f.close()
+ return
+ return
+ except IOError:
+ self.send_error(404,'File Not Found: %s' % self.path)
+
+
+#class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
+class ThreadedHTTPServer(HTTPServer, ForkingMixIn):
+ """Handle requests in a separate thread."""
+
+def main():
+ try:
+ server = ThreadedHTTPServer(('0.0.0.0', 9000), MyHandler)
+ print 'started httpserver...'
+ server.serve_forever()
+ except KeyboardInterrupt:
+ print '^C received, shutting down server'
+ server.socket.close()
+
+if __name__ == '__main__':
+ main()
diff --git a/ekgplotter/ekgplotter/index.html b/ekgplotter/ekgplotter/index.html
new file mode 100644
index 0000000..3f46bbb
--- /dev/null
+++ b/ekgplotter/ekgplotter/index.html
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/ekgplotter/ekgplotter/main.py b/ekgplotter/ekgplotter/main.py
index 1cd2542..3679c6b 100644
--- a/ekgplotter/ekgplotter/main.py
+++ b/ekgplotter/ekgplotter/main.py
@@ -1,3 +1,31 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# This file is part of sensors2osc package
+#
+# sensors2osc 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.
+#
+# sensors2osc 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 sensors2osc. If not, see .
+#
+# found the mjpeg part here, thanks for the nice code :)
+# http://hardsoftlucid.wordpress.com/2013/04/11/mjpeg-server-for-webcam-in-python-with-opencv/
+# the osc integration stuff is implemented by me
+#
+# Copyright (C) 2014 Stefan Kögl
+
+from __future__ import absolute_import
+
+import threading
+import Queue
import numpy as np
import string,cgi,time, random, socket
from os import curdir, sep
@@ -14,6 +42,10 @@ import pyqtgraph as pg
from pyqtgraph.widgets.PlotWidget import PlotWidget
+from chaosc.argparser_groups import *
+
+QtGui.QApplication.setGraphicsSystem('raster')
+
try:
from chaosc.c_osc_lib import decode_osc
@@ -21,17 +53,11 @@ except ImportError as e:
print(e)
from chaosc.osc_lib import decode_osc
-QAPP = None
-
-def mkQApp():
- if QtGui.QApplication.instance() is None:
- global QAPP
- QAPP = QtGui.QApplication([])
+QAPP = QtGui.QApplication([])
class PlotWindow(PlotWidget):
def __init__(self, title=None, **kargs):
- mkQApp()
self.win = QtGui.QMainWindow()
PlotWidget.__init__(self, **kargs)
self.win.setCentralWidget(self)
@@ -41,14 +67,61 @@ class PlotWindow(PlotWidget):
self.win.setWindowTitle(title)
+class OSCThread(threading.Thread):
+ def __init__(self, args):
+ super(OSCThread, self).__init__()
+ self.running = True
+ self.osc_sock = socket.socket(2, 2, 17)
+ self.osc_sock.bind((args.own_host, args.own_port))
+ self.osc_sock.setblocking(0)
+
+ def run(self):
+
+ while self.running:
+ reads, writes, errs = select.select([self.osc_sock], [], [], 0.05)
+ if reads:
+ osc_input = reads[0].recv(4096)
+ osc_address, typetags, messages = decode_osc(osc_input, 0, len(osc_input))
+ if osc_address.find("ekg") > -1 or osc_address.find("plot") != -1:
+ queue.put_nowait((osc_address, messages))
+ else:
+ queue.put_nowait(("/bjoern/ekg", [0]))
+ queue.put_nowait(("/merle/ekg", [0]))
+ queue.put_nowait(("/uwe/ekg", [0]))
+ print "OSCThread is going down"
+
+
+queue = Queue.Queue()
+
class MyHandler(BaseHTTPRequestHandler):
+
def do_GET(self):
- print "get"
- global plotValues
+
+ self.thread = thread = OSCThread()
+ thread.daemon = True
+ thread.start()
+
+ actors = list()
+ is_item1 = True
+ is_item2 = True
+ is_item3 = True
+
+ def setPositions():
+ for ix, item in enumerate(actors):
+ item.setPos(0, ix*6)
+
+
+ def scale_data(data, ix, max_items):
+ scale = 254 / max_items * ix
+ return [value / max_items + scale for value in data]
+
+
try:
+
self.path=re.sub('[^.a-zA-Z0-9]', "",str(self.path))
if self.path=="" or self.path==None or self.path[:1]==".":
return
+
if self.path.endswith(".html"):
f = open(curdir + sep + self.path)
self.send_response(200)
@@ -56,20 +129,26 @@ class MyHandler(BaseHTTPRequestHandler):
self.end_headers()
self.wfile.write(f.read())
f.close()
- return
- if self.path.endswith(".mjpeg"):
- self.send_response(200)
+ elif self.path.endswith(".mjpeg"):
+ data_points = 1000
- plot_data1 = deque([0] * 100)
- plot_data2 = deque([254/3] * 100)
- plot_data3 = deque([254/3*2] * 100)
- plt = PlotWindow(title="EKG", name="Merle")
- plt.addLegend()
- #plt = pg.plot(pen=(0, 3*1.3))
- plt.resize(1280, 720)
- plotItem1 = pg.PlotCurveItem(pen=(0, 3*1.3), name="bjoern")
- plotItem2 = pg.PlotCurveItem(pen=(1, 3*1.3), name="merle")
- plotItem3 = pg.PlotCurveItem(pen=(2, 3*1.3), name="uwe")
+ self.send_response(200)
+ plot_data1 = data = deque([0] * data_points)
+ plot_data2 = data = deque([0] * data_points)
+ plot_data3 = data = deque([0] * data_points)
+ plt = PlotWidget(title="EKG
", name="Merle")
+ plt.hide()
+ plotItem1 = pg.PlotCurveItem(pen=pg.mkPen('r', width=2), name="bjoern")
+ plotItem2 = pg.PlotCurveItem(pen=pg.mkPen('g', width=2), name="merle")
+ plotItem3 = pg.PlotCurveItem(pen=pg.mkPen('b', width=2), name="uwe")
+ print type(plotItem1)
+ pen = pg.mkPen(254, 254, 254)
+ plotItem1.setShadowPen(pen=pen, width=6, cosmetic=True)
+ plotItem2.setShadowPen(pen=pen, width=6, cosmetic=True)
+ plotItem3.setShadowPen(pen=pen, width=6, cosmetic=True)
+ actors.append(plotItem1)
+ actors.append(plotItem2)
+ actors.append(plotItem3)
plotItem1.setPos(0, 0*6)
plotItem2.setPos(0, 1*6)
plotItem3.setPos(0, 2*6)
@@ -77,93 +156,138 @@ class MyHandler(BaseHTTPRequestHandler):
plt.addItem(plotItem2)
plt.addItem(plotItem3)
- plt.setLabel('left', "EKG")
- plt.setLabel('bottom', "Time")
+ plt.setLabel('left', "Amplitude
")
+ plt.setLabel('bottom', "Time
")
plt.showGrid(True, True)
ba = plt.getAxis("bottom")
bl = plt.getAxis("left")
ba.setTicks([])
bl.setTicks([])
plt.setYRange(0, 254)
- print type(plt)
+
self.wfile.write("Content-Type: multipart/x-mixed-replace; boundary=--aaboundary")
self.wfile.write("\r\n\r\n")
- osc_sock = socket.socket(2, 2, 17)
- osc_sock.bind(("", 10000))
- osc_sock.setblocking(0)
- last = time.time()
- now = last
+
+
+ plt.resize(1280, 720)
while 1:
- for i in xrange(3):
- reads, writes, errs = select.select([osc_sock], [], [], 0.01)
- #print reads, writes, errs
- if reads:
- osc_input = reads[0].recv(4096)
- osc_address, typetags, args = decode_osc(osc_input, 0, len(osc_input))
- #print "osc", osc_address, typetags, args
- if osc_address.startswith("/bjoern"):
- plot_data1.appendleft(args[0] / 3)
- plot_data1.pop()
- elif osc_address.startswith("/merle"):
- plot_data2.appendleft(args[0] / 3 + 254/3)
- plot_data2.pop()
- elif osc_address.startswith("/uwe"):
- plot_data3.appendleft(args[0] / 3 + 254/3*2)
- plot_data3.pop()
+ while 1:
+ try:
+ osc_address, args = queue.get_nowait()
+ except Queue.Empty:
+ break
- plotItem1.setData(y=np.array(plot_data1), clear=True)
- plotItem2.setData(y=np.array(plot_data2), clear=True)
- plotItem3.setData(y=np.array(plot_data3), clear=True)
- #item = plt.plot(plot_data1, pen=(0, 3*1.3), clear=True)
+ value = args[0]
+ if osc_address == "/bjoern/ekg":
+ plot_data1.append(value)
+ plot_data1.popleft()
+ try:
+ plotItem1.setData(y=np.array(scale_data(plot_data1, actors.index(plotItem1), len(actors))), clear=True)
+ except ValueError:
+ pass
+ elif osc_address == "/merle/ekg":
+ plot_data2.append(value)
+ plot_data2.popleft()
+ try:
+ plotItem2.setData(y=np.array(scale_data(plot_data2, actors.index(plotItem2), len(actors))), clear=True)
+ except ValueError:
+ pass
+ elif osc_address == "/uwe/ekg":
+ plot_data3.append(value)
+ plot_data3.popleft()
+ try:
+ plotItem3.setData(y=np.array(scale_data(plot_data3, actors.index(plotItem3), len(actors))), clear=True)
+ except ValueError:
+ pass
+ elif osc_address == "/plot/uwe":
+ if value == 1 and is_item3 == False:
+ print "uwe on"
+ plt.addItem(plotItem3)
+ is_item3 = True
+ actors.append(plotItem3)
+ setPositions()
+ elif value == 0 and is_item3 == True:
+ print "uwe off"
+ plt.removeItem(plotItem3)
+ is_item3 = False
+ actors.remove(plotItem3)
+ setPositions()
+ elif osc_address == "/plot/merle":
+ if value == 1 and is_item2 == False:
+ print "merle on"
+ plt.addItem(plotItem2)
+ is_item2 = True
+ actors.append(plotItem2)
+ setPositions()
+ elif value == 0 and is_item2 == True:
+ print "merle off"
+ plt.removeItem(plotItem2)
+ is_item2 = False
+ actors.remove(plotItem2)
+ setPositions()
+ elif osc_address == "/plot/bjoern":
+ if value == 1 and is_item1 == False:
+ print "bjoern on"
+ plt.addItem(plotItem1)
+ is_item1 = True
+ actors.append(plotItem1)
+ setPositions()
+ elif value == 0 and is_item1 == True:
+ print "bjoern off"
+ plt.removeItem(plotItem1)
+ is_item1 = False
+ actors.remove(plotItem1)
+ setPositions()
exporter = pg.exporters.ImageExporter.ImageExporter(plt.plotItem)
- exporter.parameters()['width'] = 1280
- #exporter.parameters()['height'] = 720
- name = 'tmpfile'
- img = exporter.export(name, True)
+ img = exporter.export("tmpfile", True)
buffer = QBuffer()
- buffer.open(QIODevice.ReadWrite)
+ buffer.open(QIODevice.WriteOnly)
img.save(buffer, "JPG", 100)
JpegData = buffer.data()
- self.wfile.write("--aaboundary\r\n")
- self.wfile.write("Content-Type: image/jpeg\r\n")
- self.wfile.write("Content-length: %d\r\n\r\n" % len(JpegData))
- self.wfile.write(JpegData)
- self.wfile.write("\r\n\r\n\r\n")
- now = time.time()
- dur = now - last
- print dur
- wait = 0.04 - dur
- if wait > 0:
- time.sleep(wait)
- last = now
- return
- if self.path.endswith(".jpeg"):
+ del buffer
+ self.wfile.write("--aaboundary\r\nContent-Type: image/jpeg\r\nContent-length: %d\r\n\r\n%s\r\n\r\n\r\n" % (len(JpegData), JpegData))
+
+ elif self.path.endswith(".jpeg"):
f = open(curdir + sep + self.path)
self.send_response(200)
self.send_header('Content-type','image/jpeg')
self.end_headers()
self.wfile.write(f.read())
f.close()
- return
return
+ except (KeyboardInterrupt, SystemError):
+ thread.running = False
+ thread.join()
except IOError:
self.send_error(404,'File Not Found: %s' % self.path)
+ def __del__(self):
+ self.thread.running = False
+ self.thread.join()
+
+
+class JustAHTTPServer(HTTPServer):
+ pass
-#class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
-class ThreadedHTTPServer(HTTPServer, ForkingMixIn):
- """Handle requests in a separate thread."""
def main():
+ a = create_arg_parser("ekgplotter")
+ add_main_group(a)
+ add_chaosc_group(a)
+ add_subscriber_group(a, "ekgplotter")
+ args = finalize_arg_parser(a)
+
try:
- server = ThreadedHTTPServer(('0.0.0.0', 9000), MyHandler)
+ server = JustAHTTPServer(('0.0.0.0', 9000), MyHandler)
print 'started httpserver...'
server.serve_forever()
except KeyboardInterrupt:
print '^C received, shutting down server'
server.socket.close()
+
if __name__ == '__main__':
main()
+
diff --git a/ekgplotter/setup.py b/ekgplotter/setup.py
index 2d45c49..3cb5b9a 100644
--- a/ekgplotter/setup.py
+++ b/ekgplotter/setup.py
@@ -22,7 +22,7 @@ setup(
exclude_package_data = {'': ['.gitignore']},
- install_requires=[],
+ install_requires=["pyqtgraph"],
# installing unzipped
zip_safe = False,