267 lines
10 KiB
Python
267 lines
10 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
Demonstrates use of PlotWidget class. This is little more than a
|
|
GraphicsView with a PlotItem placed in its center.
|
|
"""
|
|
|
|
|
|
|
|
from collections import deque
|
|
|
|
from PyQt4 import QtNetwork
|
|
from pyqtgraph.Qt import QtGui, QtCore
|
|
import numpy as np
|
|
import pyqtgraph as pg
|
|
|
|
import numpy as np
|
|
|
|
|
|
try:
|
|
from chaosc.c_osc_lib import decode_osc
|
|
except ImportError as e:
|
|
print(e)
|
|
from chaosc.osc_lib import decode_osc
|
|
|
|
|
|
|
|
class OSCPlotter(QtGui.QWidget):
|
|
def __init__(self, parent=None):
|
|
super(OSCPlotter, self).__init__(parent)
|
|
self.plot_data1 = deque([0] * 100)
|
|
self.plot_data2 = deque([254 * 0.3] * 100)
|
|
self.plot_data3 = deque([254 * 0.6] * 100)
|
|
self.is_item1 = True
|
|
self.is_item2 = True
|
|
self.is_item3 = True
|
|
self.osc_sock = QtNetwork.QUdpSocket(self)
|
|
self.osc_sock.bind(10000)
|
|
self.osc_sock.readyRead.connect(self.receive_osc)
|
|
self.tcpServer = QtNetwork.QTcpServer(self)
|
|
self.tcpServer.listen(QtNetwork.QHostAddress("0.0.0.0"), 9000)
|
|
self.tcpServer.newConnection.connect(self.addConnection)
|
|
self.connections = []
|
|
self.streams = []
|
|
self.streaming_timer = QtCore.QTimer(self)
|
|
self.streaming_timer.timeout.connect(self.sendMJpeg)
|
|
self.streaming_timer.start(20)
|
|
|
|
|
|
def addConnection(self):
|
|
clientConnection = self.tcpServer.nextPendingConnection()
|
|
#clientConnection.nextBlockSize = 0
|
|
self.connections.append(clientConnection)
|
|
|
|
clientConnection.readyRead.connect(self.receiveMessage)
|
|
clientConnection.disconnected.connect(self.removeConnection)
|
|
clientConnection.error.connect(self.socketError)
|
|
|
|
def removeConnection(self):
|
|
pass
|
|
|
|
def socketError(self):
|
|
pass
|
|
|
|
def receiveMessage(self):
|
|
for ix, s in enumerate(self.connections):
|
|
if s.bytesAvailable() > 0:
|
|
stream = QtCore.QDataStream(s)
|
|
stream.setVersion(QtCore.QDataStream.Qt_4_8)
|
|
|
|
#if s.nextBlockSize == 0:
|
|
#if s.bytesAvailable() < 4:
|
|
#return
|
|
#s.nextBlockSize = stream.readUInt32()
|
|
#if s.bytesAvailable() < s.nextBlockSize:
|
|
#return
|
|
|
|
textFromClient = stream.readRawData(s.bytesAvailable())
|
|
print "data", repr(textFromClient)
|
|
socketId = s.socketDescriptor()
|
|
if textFromClient.startswith("GET /index.html"):
|
|
self.sendMessage("HTTP/1.1 200 Ok\r\nContent-Language: en\r\nContent-type: text/html; charset=\"utf-8\"\r\n\r\n" + open("index.html").read() + "\r\n\r\n",
|
|
s.socketDescriptor())
|
|
elif textFromClient.startswith("GET /camera.jpg"):
|
|
self.sendImage(socketId)
|
|
elif textFromClient.startswith("GET /camera.mjpeg"):
|
|
self.prepareMJpeg(socketId)
|
|
#self.sendImage(s.socketDescriptor())
|
|
else:
|
|
self.sendMessage("HTTP/1.1 404 Not Found\r\n\r\n", s.socketDescriptor())
|
|
|
|
|
|
def sendMessage(self, text, socketId):
|
|
for s in self.connections:
|
|
if s.socketDescriptor() == socketId:
|
|
print "sendMessage"
|
|
|
|
reply = QtCore.QByteArray()
|
|
stream = QtCore.QDataStream(reply, QtCore.QIODevice.WriteOnly)
|
|
#stream.setVersion(QtCore.QDataStream.Qt_4_8)
|
|
stream.writeString(text)
|
|
|
|
s.write(reply)
|
|
s.close()
|
|
|
|
|
|
def prepareMJpeg(self, socketId):
|
|
for s in self.connections:
|
|
if s.socketDescriptor() == socketId:
|
|
self.streams.append(socketId)
|
|
reply = QtCore.QByteArray()
|
|
stream = QtCore.QDataStream(reply, QtCore.QIODevice.WriteOnly)
|
|
stream.setVersion(QtCore.QDataStream.Qt_4_8)
|
|
stream.writeRawData("HTTP/1.1 200 OK\r\nContent-Type: multipart/x-mixed-replace; boundary=--aaboundary\r\n\r\n")
|
|
s.write(reply)
|
|
#s.close()
|
|
|
|
|
|
def sendMJpeg(self):
|
|
reply = QtCore.QByteArray()
|
|
stream = QtCore.QDataStream(reply, QtCore.QIODevice.WriteOnly)
|
|
stream.setVersion(QtCore.QDataStream.Qt_4_8)
|
|
stream.writeRawData("--aaboundary\r\nContent-Type: image/jpeg\r\nContent-length: %d\r\n\r\n%s\r\n\r\n\r\n" % (len(self.jpeg_data), self.jpeg_data))
|
|
for socketId in self.streams:
|
|
for connection in self.connections:
|
|
if connection.socketDescriptor() == socketId:
|
|
connection.write(reply)
|
|
#connection.close()
|
|
|
|
|
|
def sendImage(self, socketId):
|
|
for connection in self.connections:
|
|
if connection.socketDescriptor() == socketId:
|
|
reply = QtCore.QByteArray()
|
|
stream = QtCore.QDataStream(reply, QtCore.QIODevice.WriteOnly)
|
|
stream.setVersion(QtCore.QDataStream.Qt_4_8)
|
|
|
|
#tmp = open("camera.jpg", "rb").read()
|
|
header = QtCore.QString("HTTP/1.1 200 OK\r\nContent-Type: image/jpeg\r\nContent-length: %d\r\n\r\n" % len(self.jpeg_data))
|
|
stream.writeRawData(header)
|
|
stream.writeRawData(self.jpeg_data)
|
|
stream.writeRawData("\r\n\r\n\r\n")
|
|
connection.write(reply)
|
|
connection.close()
|
|
|
|
|
|
def init(self):
|
|
self.plt = pg.PlotWidget(name='EKG') ## giving the plots names allows us to link their axes together
|
|
#self.legend = self.plt.addLegend()
|
|
|
|
l = QtGui.QVBoxLayout()
|
|
self.statusLabel = QtGui.QLabel("Listening for broadcasted messages")
|
|
self.setLayout(l)
|
|
l.addWidget(self.plt)
|
|
l.addWidget(self.statusLabel)
|
|
|
|
self.plotItem1 = pg.PlotCurveItem(pen=pg.mkPen('r', width=4), name="bjoern")
|
|
self.plotItem2 = pg.PlotCurveItem(pen=pg.mkPen('g', width=4), name="merle")
|
|
self.plotItem3 = pg.PlotCurveItem(pen=pg.mkPen('b', width=4), name="uwe")
|
|
#self.plotItem1.setPos(0, 0*6)
|
|
#self.plotItem2.setPos(0, 1*6)
|
|
#self.plotItem3.setPos(0, 2*6)
|
|
self.plt.addItem(self.plotItem1)
|
|
self.plt.addItem(self.plotItem2)
|
|
self.plt.addItem(self.plotItem3)
|
|
self.plt.setLabel('left', "EKG")
|
|
self.plt.setLabel('bottom', "Time")
|
|
self.plt.showGrid(True, True)
|
|
ba = self.plt.getAxis("bottom")
|
|
bl = self.plt.getAxis("left")
|
|
ba.setTicks([])
|
|
bl.setTicks([])
|
|
self.plt.setYRange(0, 254)
|
|
self.plotItem1.setData(y=np.array(self.plot_data1), clear=True)
|
|
self.plotItem2.setData(y=np.array(self.plot_data2), clear=True)
|
|
self.plotItem3.setData(y=np.array(self.plot_data3), clear=True)
|
|
#self.plotItem1.setShadowPen(pg.mkPen((200, 200, 200), width=6, cosmetic=True))
|
|
#self.plotItem2.setShadowPen(pg.mkPen((200, 200, 200), width=6, cosmetic=True))
|
|
#self.plotItem3.setShadowPen(pg.mkPen((200, 200, 200), width=6, cosmetic=True))
|
|
|
|
|
|
|
|
def receive_osc(self):
|
|
#print "receive_osc"
|
|
while self.osc_sock.hasPendingDatagrams():
|
|
packet, address, port = self.osc_sock.readDatagram(self.osc_sock.pendingDatagramSize())
|
|
osc_address, typetags, args = decode_osc(packet, 0, len(packet))
|
|
|
|
#print "osc", osc_address, args[0]
|
|
self.statusLabel.setText(osc_address)
|
|
update = False
|
|
if osc_address == "/bjoern/ekg":
|
|
self.plot_data1.appendleft(args[0] / 3)
|
|
self.plot_data1.pop()
|
|
update = True
|
|
elif osc_address == "/merle/ekg":
|
|
self.plot_data2.appendleft(args[0] / 3 + 254/3)
|
|
self.plot_data2.pop()
|
|
update = True
|
|
elif osc_address == "/uwe/ekg":
|
|
self.plot_data3.appendleft(args[0] /3 + 254/3*2)
|
|
self.plot_data3.pop()
|
|
update = True
|
|
#elif osc_address == "/plot/uwe":
|
|
#if args[0] == 1 and self.is_item3 == False:
|
|
#self.plt.addItem(self.plotItem3)
|
|
#self.is_item3 = True
|
|
##self.legend.addItem(self.plotItem3, "uwe")
|
|
#elif args[0] == 0 and self.is_item3 == True:
|
|
#self.plt.removeItem(self.plotItem3)
|
|
#self.is_item3 = False
|
|
##self.legend.removeItem("uwe")
|
|
#elif osc_address == "/plot/merle":
|
|
#if args[0] == 1 and self.is_item2 == False:
|
|
#self.plt.addItem(self.plotItem2)
|
|
#self.is_item2 = True
|
|
##self.legend.addItem(self.plotItem2, "merle")
|
|
#elif args[0] == 0 and self.is_item2 == True:
|
|
#self.plt.removeItem(self.plotItem2)
|
|
#self.is_item2 = True
|
|
##self.legend.removeItem("merle")
|
|
#elif osc_address == "/plot/bjoern":
|
|
#if args[0] == 1 and self.is_item1 == False:
|
|
#self.plt.addItem(self.plotItem1)
|
|
#self.is_item1 = True
|
|
##self.legend.addItem(self.plotItem1, name="bjoern")
|
|
#elif args[0] == 0 and self.is_item1 == True:
|
|
#self.plt.removeItem(self.plotItem1)
|
|
#self.is_item1 = False
|
|
##self.legend.removeItem("bjoern")
|
|
|
|
if update:
|
|
self.plotItem1.setData(y=np.array(self.plot_data1), clear=True)
|
|
self.plotItem2.setData(y=np.array(self.plot_data2), clear=True)
|
|
self.plotItem3.setData(y=np.array(self.plot_data3), clear=True)
|
|
#item = plt.plot(plot_data1, pen=(0, 3*1.3), clear=True)
|
|
|
|
exporter = pg.exporters.ImageExporter.ImageExporter(self.plt.plotItem)
|
|
exporter.parameters()['width'] = 1280
|
|
#exporter.parameters()['height'] = 720
|
|
name = 'tmpfile'
|
|
img = exporter.export(name, True)
|
|
buffer = QtCore.QBuffer()
|
|
buffer.open(QtCore.QIODevice.ReadWrite)
|
|
img.save(buffer, "JPG", 100)
|
|
self.jpeg_data = buffer.data()
|
|
|
|
|
|
|
|
#QtGui.QApplication.setGraphicsSystem('raster')
|
|
app = QtGui.QApplication([])
|
|
mw = QtGui.QMainWindow()
|
|
mw.setWindowTitle('pyqtgraph example: PlotWidget')
|
|
mw.resize(1280, 720)
|
|
cw = OSCPlotter()
|
|
cw.init()
|
|
mw.setCentralWidget(cw)
|
|
|
|
mw.show()
|
|
|
|
|
|
|
|
## Start Qt event loop unless running in interactive mode or using pyside.
|
|
if __name__ == '__main__':
|
|
import sys
|
|
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
|
|
QtGui.QApplication.instance().exec_()
|