diff --git a/app/app.pri b/app/app.pri
index 007ea3671b589a5f7d6bb913cc28d0bb02a12c24..21388a6a3eab19e9f25988883e0f9348f2d16a11 100644
--- a/app/app.pri
+++ b/app/app.pri
@@ -1,10 +1,12 @@
 QT += \
     core \
-    network
+    network \
+    websockets
 
 QT -= gui
 
 HEADERS += \
+    $${PWD}/src/websockets/websocketserver.h \
     $${PWD}/src/handlers/confighandler.h \
     $${PWD}/src/handlers/systemhandler.h \
     $${PWD}/src/handlers/ocshandler.h \
@@ -12,6 +14,7 @@ HEADERS += \
 
 SOURCES += \
     $${PWD}/src/main.cpp \
+    $${PWD}/src/websockets/websocketserver.cpp \
     $${PWD}/src/handlers/confighandler.cpp \
     $${PWD}/src/handlers/systemhandler.cpp \
     $${PWD}/src/handlers/ocshandler.cpp \
diff --git a/app/src/main.cpp b/app/src/main.cpp
index 23fe103dec3d427b52043d5265b2ff7f5a2e50c3..a702c0219fd173d6a2ed3b00740b59896e85e86f 100644
--- a/app/src/main.cpp
+++ b/app/src/main.cpp
@@ -1,20 +1,24 @@
+#include <QStringList>
 #include <QJsonObject>
 //#include <QTranslator>
 //#include <QLocale>
 #include <QCommandLineParser>
+#include <QCommandLineOption>
 #include <QCoreApplication>
+#include <QDebug>
 
 #include "handlers/confighandler.h"
-#include "handlers/systemhandler.h"
-#include "handlers/ocshandler.h"
-#include "handlers/itemhandler.h"
+//#include "handlers/systemhandler.h"
+//#include "handlers/ocshandler.h"
+//#include "handlers/itemhandler.h"
+#include "websockets/websocketserver.h"
 
 int main(int argc, char *argv[])
 {
     // Init
     QCoreApplication app(argc, argv);
 
-    ConfigHandler *configHandler = new ConfigHandler();
+    ConfigHandler *configHandler = new ConfigHandler(&app);
     QJsonObject appConfigApplication = configHandler->getAppConfigApplication();
 
     app.setApplicationName(appConfigApplication["name"].toString());
@@ -33,7 +37,27 @@ int main(int argc, char *argv[])
     clParser.setApplicationDescription(appConfigApplication["description"].toString());
     clParser.addHelpOption();
     clParser.addVersionOption();
+
+    // Port 49152-61000 will available as ephemeral port
+    // https://en.wikipedia.org/wiki/Ephemeral_port
+    QCommandLineOption clOptionPort(QStringList() << "p" << "port", "Port for websocket server [default: 49152].", "port", "49152");
+    clParser.addOption(clOptionPort);
+
     clParser.process(app);
 
+    int port = clParser.value(clOptionPort).toInt();
+
+    // Setup websocket server
+    WebSocketServer *wsServer = new WebSocketServer(appConfigApplication["id"].toString(), port, &app);
+    QObject::connect(wsServer, &WebSocketServer::stopped, &app, &QCoreApplication::quit);
+
+    if (wsServer->start()) {
+        qDebug() << "Websocket server started at:" << wsServer->serverUrl().toString();
+    }
+    else {
+        qCritical() << "Failed to start websocket server:" << wsServer->errorString();
+        return 1;
+    }
+
     return app.exec();
 }
diff --git a/app/src/websockets/websocketserver.cpp b/app/src/websockets/websocketserver.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c1aed4614b6c43989ab2a531f1f54fe459c088bf
--- /dev/null
+++ b/app/src/websockets/websocketserver.cpp
@@ -0,0 +1,94 @@
+#include "websocketserver.h"
+
+#include <QHostAddress>
+#include <QWebSocketServer>
+#include <QWebSocket>
+
+#include "qtlib_json.h"
+
+WebSocketServer::WebSocketServer(const QString &serverName, quint16 serverPort, QObject *parent)
+    : QObject(parent), serverName_(serverName), serverPort_(serverPort)
+{
+    wsServer_ = new QWebSocketServer(serverName_, QWebSocketServer::NonSecureMode, this);
+    connect(wsServer_, &QWebSocketServer::newConnection, this, &WebSocketServer::wsNewConnection);
+    connect(wsServer_, &QWebSocketServer::closed, this, &WebSocketServer::stopped);
+}
+
+WebSocketServer::~WebSocketServer()
+{
+    stop();
+    wsServer_->deleteLater();
+}
+
+bool WebSocketServer::start()
+{
+    if (wsServer_->listen(QHostAddress::Any, serverPort_)) {
+        emit started();
+        return true;
+    }
+    return false;
+}
+
+void WebSocketServer::stop()
+{
+    wsServer_->close();
+}
+
+bool WebSocketServer::isError()
+{
+    if (wsServer_->error() != QWebSocketProtocol::CloseCodeNormal) {
+        return true;
+    }
+    return false;
+}
+
+QString WebSocketServer::errorString()
+{
+    return wsServer_->errorString();
+}
+
+QUrl WebSocketServer::serverUrl()
+{
+    return wsServer_->serverUrl();
+}
+
+void WebSocketServer::wsNewConnection()
+{
+    QWebSocket *wsClient = wsServer_->nextPendingConnection();
+    connect(wsClient, &QWebSocket::binaryMessageReceived, this, &WebSocketServer::wsBinaryMessageReceived);
+    connect(wsClient, &QWebSocket::textMessageReceived, this, &WebSocketServer::wsTextMessageReceived);
+    connect(wsClient, &QWebSocket::disconnected, this, &WebSocketServer::wsDisconnected);
+    wsClients_ << wsClient;
+}
+
+void WebSocketServer::wsBinaryMessageReceived(const QByteArray &message)
+{
+    QWebSocket *wsClient = qobject_cast<QWebSocket *>(sender());
+    if (wsClient) {
+        wsClient->sendBinaryMessage(message);
+    }
+}
+
+void WebSocketServer::wsTextMessageReceived(const QString &message)
+{
+    QWebSocket *wsClient = qobject_cast<QWebSocket *>(sender());
+    if (wsClient) {
+        qtlib::Json json(message.toUtf8());
+        if (json.isValid()) {
+            QJsonObject jsonObject = json.toObject();
+            if (jsonObject["method"].toString() == "stop") {
+                stop();
+            }
+        }
+        wsClient->sendTextMessage(message);
+    }
+}
+
+void WebSocketServer::wsDisconnected()
+{
+    QWebSocket *wsClient = qobject_cast<QWebSocket *>(sender());
+    if (wsClient) {
+        wsClients_.removeAll(wsClient);
+        wsClient->deleteLater();
+    }
+}
diff --git a/app/src/websockets/websocketserver.h b/app/src/websockets/websocketserver.h
new file mode 100644
index 0000000000000000000000000000000000000000..01d4591ba9792cb4699d7405699f94f623312fd6
--- /dev/null
+++ b/app/src/websockets/websocketserver.h
@@ -0,0 +1,39 @@
+#pragma once
+
+#include <QObject>
+#include <QUrl>
+
+class QWebSocketServer;
+class QWebSocket;
+
+class WebSocketServer : public QObject
+{
+    Q_OBJECT
+
+public:
+    explicit WebSocketServer(const QString &serverName, quint16 serverPort = 0, QObject *parent = 0);
+    ~WebSocketServer();
+
+signals:
+    void started();
+    void stopped();
+
+public slots:
+    bool start();
+    void stop();
+    bool isError();
+    QString errorString();
+    QUrl serverUrl();
+
+private slots:
+    void wsNewConnection();
+    void wsBinaryMessageReceived(const QByteArray &message);
+    void wsTextMessageReceived(const QString &message);
+    void wsDisconnected();
+
+private:
+    QString serverName_;
+    quint16 serverPort_;
+    QWebSocketServer *wsServer_;
+    QList<QWebSocket *> wsClients_;
+};