Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add socket into backend. That allow record/stop by python #56

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion source/Miniscope-DAQ-QT-Software.pro
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
QT += qml quick widgets
QT += qml quick widgets network
CONFIG += c++11

QT += 3dcore
Expand Down Expand Up @@ -28,6 +28,7 @@ SOURCES += \
main.cpp \
miniscope.cpp \
newquickview.cpp \
tcpserver.cpp \
tracedisplay.cpp \
videodevice.cpp \
videodisplay.cpp \
Expand Down Expand Up @@ -58,6 +59,7 @@ HEADERS += \
datasaver.h \
miniscope.h \
newquickview.h \
tcpserver.h \
tracedisplay.h \
videodevice.h \
videodisplay.h \
Expand Down
5 changes: 5 additions & 0 deletions source/backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "datasaver.h"
#include "behaviortracker.h"
#include "tracedisplay.h"
#include "tcpserver.h"

#ifdef USE_USB
#include <libusb.h>
Expand Down Expand Up @@ -920,6 +921,10 @@ void backEnd::constructUserConfigGUI()
controlPanel = new ControlPanel(this, m_userConfig);
QObject::connect(this, SIGNAL (sendMessage(QString) ), controlPanel, SLOT( receiveMessage(QString)));

// Create tcp server control GUI
TcpServer *tcpServer = new TcpServer(controlPanel, this);
tcpServer->on_socket_activate(true);

// Make trace display
if (!ucTraceDisplay.isEmpty()) {
if (ucTraceDisplay["enabled"].toBool(true))
Expand Down
4 changes: 2 additions & 2 deletions source/controlpanel.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class ControlPanel : public QObject
void createView();
void connectSnS();
void fillUCEditText();
QObject *rootObject;
// void setUserConfig(QJsonObject userConfig) {m_userConfig = userConfig;}

public slots:
Expand All @@ -36,10 +37,9 @@ public slots:

private:
NewQuickView *view;
QObject *rootObject;

QQuickItem *messageTextArea;
QQuickItem *recordTimeText;

QJsonObject m_userConfig;
double currentRecordTime;
int m_ucRecordLengthinSeconds;
Expand Down
186 changes: 186 additions & 0 deletions source/tcpserver.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
#include <QQuickItem>
#include "tcpserver.h"

using namespace TCPSERVER_PRIVATE;

TcpServer::TcpServer(ControlPanel *ctl, QObject *parent):
QTcpServer(parent), controlPanel(ctl)
{
connect(this, SIGNAL(recordButtonClick()),
controlPanel->rootObject->findChild<QQuickItem*>("bRecord"),
SIGNAL(activated()));
connect(this, SIGNAL(stopButtonClick()),
controlPanel->rootObject->findChild<QQuickItem*>("bStop"),
SIGNAL(activated()));
connect(this, SIGNAL(tell_socket_port(QString)),
controlPanel,
SLOT(receiveMessage(QString)));
}


void TcpServer::on_socket_activate(bool activate)
{
if(activate){
quint16 port = 20172;
if(listen(QHostAddress::Any, port)
|| listen(QHostAddress::Any, port+1)
|| listen(QHostAddress::Any, port+2)
|| listen(QHostAddress::Any, port+3)
|| listen(QHostAddress::Any, port+4)
|| listen(QHostAddress::Any))
{
qDebug() << "Server started!" << this->serverPort();
emit tell_socket_port(QString("Connect socket to PORT [%1].").arg(this->serverPort()));
}
else
{
qDebug() << "Server could not start";
emit tell_socket_port(QString("Warning: connect socket failed"));
}
}
else{
this->close();
}
}

// This function is called by QTcpServer when a new connection is available.
void TcpServer::incomingConnection(qintptr socketDescriptor)
{
// We have a new connection
qDebug() << socketDescriptor << " Connecting...";

// Every new connection will be run in a newly created thread
MyThread *thread = new MyThread(socketDescriptor, this);

// connect signal/slot
// once a thread is not needed, it will be beleted later
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
}

bool TcpServer::tcpcmd_start_record(char *outmsg)
{
bool currentstuts = controlPanel->rootObject->property("recording").toBool();
if(currentstuts){
strcpy(outmsg, "Error! Already started before.");
return false;
}
bool btn_enabled = true;
if(!btn_enabled){
strcpy(outmsg, "Error! Device not connected.");
return false;
}
emit recordButtonClick();
strcpy(outmsg, "OK! Task should be starting.");
return true;
}

bool TcpServer::tcpcmd_stop_record(char *outmsg)
{
bool currentstuts = controlPanel->rootObject->property("recording").toBool();
if(!currentstuts){
strcpy(outmsg, "Error! Already stopped before.");
return false;
}
bool btn_enabled = true;
if(!btn_enabled){
strcpy(outmsg, "Error! Device not connected.");
return false;
}
emit stopButtonClick();
strcpy(outmsg, "OK! Task should be stopping.");
return true;
}

int TcpServer::tcpcmd_query_record(char *outmsg)
{
bool btn_enabled = true;
if(!btn_enabled){
strcpy(outmsg, "Device not connected.");
return 0;
}
bool currentstuts = controlPanel->rootObject->property("recording").toBool();
if(currentstuts){
strcpy(outmsg, "Running.");
return 2;
}
else{
strcpy(outmsg, "Stopped.");
return 1;
}
}

MyThread::MyThread(qintptr ID, TcpServer *tcpServer, QObject *parent) :
QThread(parent)
{
this->socketDescriptor = ID;
this->tcpServer = tcpServer;
}

void MyThread::run()
{
// thread starts here
qDebug() << " Thread started";

socket = new QTcpSocket();

// set the ID
if(!socket->setSocketDescriptor(this->socketDescriptor))
{
// something's wrong, we just emit a signal
emit error(socket->error());
return;
}

// connect socket and signal
// note - Qt::DirectConnection is used because it's multithreaded
// This makes the slot to be invoked immediately, when the signal is emitted.

connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()), Qt::DirectConnection);
connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()));

// We'll have multiple clients, we want to know which is which
qDebug() << socketDescriptor << " Client connected";

// make this thread a loop,
// thread will stay alive so that signal/slot to function properly
// not dropped out in the middle when thread dies
exec();
}

void MyThread::disconnected()
{
qDebug() << socketDescriptor << " Disconnected";
socket->deleteLater();
exit(0);
}

void MyThread::readyRead()
{
const int MaxLength = 1024;
char buffer[MaxLength+1];
qint64 byteCount = socket->read(buffer, MaxLength);
buffer[byteCount] = 0;
qDebug() << socket->bytesAvailable() << buffer;

char response[MaxLength+1];
if(strcmp(buffer, "start_record")==0)
{
tcpServer->tcpcmd_start_record(response);
}
else if(strcmp(buffer, "stop_record")==0)
{
tcpServer->tcpcmd_stop_record(response);
}
else if(strcmp(buffer, "query_record")==0)
{
tcpServer->tcpcmd_query_record(response);
}
else
{
strcpy(response, "Error! Not a valid command.");
}
socket->write(response);
socket->flush();
socket->waitForBytesWritten(100);
}
59 changes: 59 additions & 0 deletions source/tcpserver.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#ifndef TCPSERVER_H
#define TCPSERVER_H

#include <QObject>
#include <QThread>
#include <QTcpSocket>
#include <QTcpServer>
#include <QDebug>
#include "controlpanel.h"


class TcpServer : public QTcpServer
{
Q_OBJECT
public:
explicit TcpServer(ControlPanel *,QObject *parent = 0);
bool tcpcmd_start_record(char *outmsg);
bool tcpcmd_stop_record(char *outmsg);
int tcpcmd_query_record(char *outmsg);

signals:
void tell_socket_port(QString port);
void recordButtonClick();
void stopButtonClick();

private:
ControlPanel *controlPanel;

public slots:
void on_socket_activate(bool activate);

protected:
void incomingConnection(qintptr socketDescriptor);
};


namespace TCPSERVER_PRIVATE{
class MyThread : public QThread
{
Q_OBJECT
public:
explicit MyThread(qintptr ID, TcpServer *tcpserver, QObject *parent = 0);
void run();

signals:
void error(QTcpSocket::SocketError socketerror);

public slots:
void readyRead();
void disconnected();

private:
TcpServer *tcpServer;
QTcpSocket *socket;
qintptr socketDescriptor;
};
}

#endif // TCPSERVER_H