From 2a803ddcf479ba70b08b199e0448521969796a14 Mon Sep 17 00:00:00 2001 From: Philippe Lelong Date: Fri, 16 Dec 2016 09:21:21 +0100 Subject: websockets mechanism implemented Signed-off-by: Philippe Lelong --- HomeScreen/qml/Home.qml | 16 +- HomeScreen/qml/MediaAreaBlank.qml | 4 + HomeScreen/qml/StatusArea.qml | 1 + HomeScreen/qml/images/Utility_Logo_Red-01.png | Bin 0 -> 7306 bytes HomeScreen/qml/images/images.qrc | 1 + HomeScreen/src/main.cpp | 5 +- HomeScreen/src2/usermanagement.cpp | 279 +++++++++++++++++++++++--- HomeScreen/src2/usermanagement.h | 63 +++++- 8 files changed, 328 insertions(+), 41 deletions(-) create mode 100644 HomeScreen/qml/images/Utility_Logo_Red-01.png diff --git a/HomeScreen/qml/Home.qml b/HomeScreen/qml/Home.qml index 8753d29..63bb385 100644 --- a/HomeScreen/qml/Home.qml +++ b/HomeScreen/qml/Home.qml @@ -51,6 +51,17 @@ Item { anchors.topMargin: 20 source: './images/visa.png' visible: false + Label { + id: cardNumber + anchors.top: parent.bottom + anchors.topMargin: 10 + anchors.horizontalCenter: parent.horizontalCenter + horizontalAlignment: Text.AlignHCenter + color: "white" + text: "111" + font.pixelSize: 20 + font.family: "Roboto" + } } Item { id: hello @@ -62,7 +73,7 @@ Item { id: helloText anchors.centerIn: parent color: "white" - text: "Hello José!" + text: "" font.pixelSize: 40 font.family: "Roboto" SequentialAnimation on font.letterSpacing { @@ -95,8 +106,9 @@ Item { sign90.visible = show } - function showVisa(show) { + function showVisa(show, num) { visa.visible = show + cardNumber.text = num; } GridView { anchors.centerIn: parent diff --git a/HomeScreen/qml/MediaAreaBlank.qml b/HomeScreen/qml/MediaAreaBlank.qml index 3d53061..48595eb 100644 --- a/HomeScreen/qml/MediaAreaBlank.qml +++ b/HomeScreen/qml/MediaAreaBlank.qml @@ -23,7 +23,11 @@ Image { source: './images/Utility_Logo_Background-01.png' Image { + objectName: "Logo_colour" anchors.centerIn: parent source: './images/Utility_Logo_Colour-01.png' + function setImage(imagePath) { + source = imagePath + } } } diff --git a/HomeScreen/qml/StatusArea.qml b/HomeScreen/qml/StatusArea.qml index 12d0d46..3d55947 100644 --- a/HomeScreen/qml/StatusArea.qml +++ b/HomeScreen/qml/StatusArea.qml @@ -144,6 +144,7 @@ Item { } } } + Component.onCompleted: root.languageChanged("en") } ColumnLayout { id: icons diff --git a/HomeScreen/qml/images/Utility_Logo_Red-01.png b/HomeScreen/qml/images/Utility_Logo_Red-01.png new file mode 100644 index 0000000..8c49068 Binary files /dev/null and b/HomeScreen/qml/images/Utility_Logo_Red-01.png differ diff --git a/HomeScreen/qml/images/images.qrc b/HomeScreen/qml/images/images.qrc index 2d8e902..1323107 100644 --- a/HomeScreen/qml/images/images.qrc +++ b/HomeScreen/qml/images/images.qrc @@ -6,5 +6,6 @@ Utility_Music_Background-01.png Utility_Radio_Background-01.png AGL_HMI_Background_NoCar-01.png + Utility_Logo_Red-01.png diff --git a/HomeScreen/src/main.cpp b/HomeScreen/src/main.cpp index 4e928c6..37648a0 100644 --- a/HomeScreen/src/main.cpp +++ b/HomeScreen/src/main.cpp @@ -75,10 +75,7 @@ int main(int argc, char *argv[]) engine.rootContext()->setContextProperty("layoutHandler", layoutHandler); engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); - QObject *home = engine.rootObjects().first()->findChild("Home"); - QObject *shortcutArea = engine.rootObjects().first()->findChild("ShortcutArea"); - QObject *statusArea = engine.rootObjects().first()->findChild("StatusArea"); - UserManagement userManagement(home, shortcutArea, statusArea); + UserManagement userManagement(engine.rootObjects().first()); Q_UNUSED(userManagement); return a.exec(); } diff --git a/HomeScreen/src2/usermanagement.cpp b/HomeScreen/src2/usermanagement.cpp index f973001..54aff23 100644 --- a/HomeScreen/src2/usermanagement.cpp +++ b/HomeScreen/src2/usermanagement.cpp @@ -1,62 +1,281 @@ #include "usermanagement.h" #include #include -UserManagement::UserManagement(QObject *home, QObject *shortcutArea, QObject *statusArea) : QObject() +#include +#include +UserManagement::UserManagement(QObject *root) : QObject() { - this->home = home; + home = root->findChild("Home"); + logo = root->findChild("Logo_colour"); + shortcutArea = root->findChild("ShortcutArea"); + statusArea = root->findChild("StatusArea"); this->appModel = home->findChild("ApplicationModel"); - this->shortcutArea = shortcutArea; - this->statusArea = statusArea; - this->currentLanguage = "en"; + sequence = 0; +#ifdef REAL_SERVER + connectWebsockets(); +#else + pSocket = NULL; connect(&timerTest, SIGNAL(timeout()), this, SLOT(slot_timerTest())); timerTest.setSingleShot(false); timerTest.start(5000); - connectWebsockets(QStringLiteral("wss://echo.websocket.org")); + launchServer(); +#endif } -void UserManagement::slot_timerTest() +void UserManagement::setUser(const User &user) { - if(currentLanguage == "fr") - currentLanguage = "en"; - else - currentLanguage = "fr"; - appModel->changeLanguage(currentLanguage); + appModel->changeLanguage(user.graphPreferredLanguage); + QMetaObject::invokeMethod(logo, "setImage", Q_ARG(QVariant, "./images/Utility_Logo_Colour-01.png")); QMetaObject::invokeMethod(home, "languageChanged"); - QMetaObject::invokeMethod(shortcutArea, "languageChanged", Q_ARG(QVariant, currentLanguage)); - QMetaObject::invokeMethod(statusArea, "languageChanged", Q_ARG(QVariant, currentLanguage)); - if(currentLanguage == "fr") { - QLocale::setDefault(QLocale("fr_FR")); - QMetaObject::invokeMethod(home, "showSign90", Q_ARG(QVariant, true)); - QMetaObject::invokeMethod(home, "showVisa", Q_ARG(QVariant, false)); - QMetaObject::invokeMethod(home, "showHello", Q_ARG(QVariant, "Bonjour José!")); - } else { - QLocale::setDefault(QLocale("en_US")); - QMetaObject::invokeMethod(home, "showSign90", Q_ARG(QVariant, false)); - QMetaObject::invokeMethod(home, "showVisa", Q_ARG(QVariant, true)); - QMetaObject::invokeMethod(home, "showHello", Q_ARG(QVariant, "Hello José!")); - } -} -void UserManagement::connectWebsockets(const QUrl &url) + QMetaObject::invokeMethod(shortcutArea, "languageChanged", Q_ARG(QVariant, user.graphPreferredLanguage)); + QMetaObject::invokeMethod(statusArea, "languageChanged", Q_ARG(QVariant, user.graphPreferredLanguage)); + QMetaObject::invokeMethod(home, "showSign90", Q_ARG(QVariant, true)); + QMetaObject::invokeMethod(home, "showVisa", Q_ARG(QVariant, true), Q_ARG(QVariant, "---- ---- ---- " + user.ccNumberMasked)); + const QString welcome = QString("%1").arg(user.graphPreferredLanguage == "fr" ? "Bonjour " : "Hello") + " "; + QMetaObject::invokeMethod(home, "showHello", Q_ARG(QVariant, welcome + user.first_name)); +} +void UserManagement::connectWebsockets() { +#ifdef REAL_SERVER + const QUrl url(REAL_SERVER); +#else + const QUrl url(QStringLiteral("ws://localhost:1234")); +#endif QSslConfiguration config = QSslConfiguration::defaultConfiguration(); config.setProtocol(QSsl::SecureProtocols); webSocket.setSslConfiguration(config); connect(&webSocket, &QWebSocket::connected, this, &UserManagement::onConnected); connect(&webSocket, &QWebSocket::disconnected, this, &UserManagement::onClosed); + if(!connect(&webSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onWebSocketError(QAbstractSocket::SocketError)))) { + qWarning() << "Failed to connect to QWebSocket::error"; + } webSocket.open(QUrl(url)); } +void UserManagement::onWebSocketError(QAbstractSocket::SocketError) +{ + qWarning()<<"Websocket error:" << webSocket.errorString(); +} + void UserManagement::onConnected() { connect(&webSocket, &QWebSocket::textMessageReceived, this, &UserManagement::onTextMessageReceived); - webSocket.sendTextMessage(QStringLiteral("Hello, world!")); - + QVariantList list; + QByteArray json; + list << 2 << QString().setNum(++sequence) << "agl-identity-agent/subscribe" << true; + listToJson(list, &json); + webSocket.sendTextMessage(QString(json)); + list .clear(); + list << 2 << QString().setNum(++sequence) << "agl-identity-agent/scan" << true; + listToJson(list, &json); + webSocket.sendTextMessage(QString(json)); } void UserManagement::onTextMessageReceived(QString message) { - qWarning()<<"message received:"< &list, QByteArray *json) const +{ + QVariant v(list); + *json = QJsonDocument::fromVariant(v).toJson(QJsonDocument::Compact); + return true; +} +bool UserManagement::jsonToList(const QByteArray &buf, QList *list) const +{ + if(!list) + return false; + QJsonParseError err; + QVariant v = QJsonDocument::fromJson(buf, &err).toVariant(); + if(err.error != 0) { + qWarning() << "Error parsing json data" << err.errorString() << buf; + *list = QList(); + return false; + } + *list = v.toList(); + return true; +} +bool UserManagement::mapToJson( const QVariantMap &map, QByteArray *json) const +{ + if(!json) + return false; + QVariant v(map); + *json = QJsonDocument::fromVariant(v).toJson(QJsonDocument::Compact); + return true; +} +bool UserManagement::jsonToMap(const QByteArray &buf, QVariantMap *map) const +{ + if(!map) + return false; + QJsonParseError err; + QVariant v = QJsonDocument::fromJson(buf, &err).toVariant(); + if(err.error != 0) { + qWarning() << "Error parsing json data" << err.errorString() << buf; + *map = QVariantMap(); + return false; + } + *map = v.toMap(); + return true; +} +#ifndef REAL_SERVER +void UserManagement::launchServer() +{ + webSocketServer = new QWebSocketServer(QStringLiteral("My Server"), + QWebSocketServer::NonSecureMode, this); + if(webSocketServer->listen(QHostAddress::Any, 1234)) { + connect(webSocketServer, &QWebSocketServer::newConnection, + this, &UserManagement::onServerNewConnection); + connect(webSocketServer, &QWebSocketServer::closed, this, &UserManagement::onServerClosed); + QTimer::singleShot(100, this, SLOT(connectWebsockets())); + } else { + qWarning()<<"unable to launch webSocket server"; + } +} +void UserManagement::onServerNewConnection() +{ + pSocket = webSocketServer->nextPendingConnection(); + connect(pSocket, &QWebSocket::textMessageReceived, this, &UserManagement::processTextMessage, Qt::UniqueConnection); + connect(pSocket, &QWebSocket::binaryMessageReceived, this, &UserManagement::processBinaryMessage, Qt::UniqueConnection); + connect(pSocket, &QWebSocket::disconnected, this, &UserManagement::serverSocketDisconnected, Qt::UniqueConnection); +} +void UserManagement::processTextMessage(QString message) +{ + QString clientDetails_1 = "{\"postal_address\":\"201 Mission Street\",\"loc\":\"37.7914374,-122.3950694\"" + ",\"country\":\"USA\",\"mail\":\"bjensen@example.com\",\"city\":\"San Francisco\",\"graphEmail\":" + "\"bjensen@example.com\",\"graphPreferredLanguage\":\"en\",\"ccNumberMasked\":\"-111\",\"ccExpYear\"" + ":\"19\",\"ccExpMonth\":\"01\",\"description\":\"Original description\",\"groups\":[],\"last_name\":\"" + "Jensen\",\"ccNumber\":\"111-2343-1121-111\",\"house_identifier\":\"ForgeRock\",\"phone\":\"" + "+1 408 555 1862\",\"name\":\"bjensen\",\"state\":\"CA\",\"common_name\":\"Barbara Jensen\",\"fax\":\"" + "+1 408 555 1862\",\"postal_code\":\"94105\",\"first_name\":\"Barbara\",\"keytoken\":\"a123456\"}"; + QString clientDetails_2 = "{\"postal_address\":\"201 Mission Street\",\"loc\":\"37.7914374,-122.3950694\"" + ",\"country\":\"USA\",\"mail\":\"bjensen@example.com\",\"city\":\"San Francisco\",\"graphEmail\":" + "\"bjensen@example.com\",\"graphPreferredLanguage\":\"fr\",\"ccNumberMasked\":\"-222\",\"ccExpYear\"" + ":\"19\",\"ccExpMonth\":\"01\",\"description\":\"Original description\",\"groups\":[],\"last_name\":\"" + "Jensen\",\"ccNumber\":\"111-2343-1121-111\",\"house_identifier\":\"ForgeRock\",\"phone\":\"" + "+1 408 555 1862\",\"name\":\"bjensen\",\"state\":\"CA\",\"common_name\":\"Barbara Jensen\",\"fax\":\"" + "+1 408 555 1862\",\"postal_code\":\"94105\",\"first_name\":\"José\",\"keytoken\":\"a123456\"}"; + QString clientDetails = clientDetails_1; + if(sequence % 2 == 1) + clientDetails = clientDetails_2; + QWebSocket *pClient = qobject_cast(sender()); + //qDebug() << "message received in server:" << message; + if (!pClient) + return; + QVariantList list; + if(!jsonToList(message.toUtf8(), &list)) + return; + if(list.size() < 2) + return; + const int messType = list.at(0).toInt(); + const QString messId = list.at(1).toString(); + const QString cmd = list.at(2).toString(); + list.clear(); + QString reply; + switch(messType) { + case 2: + if(cmd == "agl-identity-agent/subscribe") { + reply = "[3,\"999maitai999\",{\"jtype\":\"afb-reply\",\"request\":{\"status\":\"success\",\"uuid\":\"1f2f7678-6f2e-4f54-b7b5-d0d4dcbf2e41\"}}]"; + } else if (cmd == "agl-identity-agent/get") { + reply = "[3,\"999maitai99\",{\"jtype\":\"afb-reply\",\"request\":{\"status\":\"success\"},\"response\":....}]"; + reply = reply.replace("....", clientDetails); + } else { + qWarning()<<"invalid cmd received:"<sendTextMessage(reply); +} +void UserManagement::processBinaryMessage(QByteArray message) +{ + QWebSocket *pClient = qobject_cast(sender()); + qDebug() << "Binary Message received ????:" << message; + if (pClient) { + // pClient->sendBinaryMessage(message); + } +} +void UserManagement::serverSocketDisconnected() +{ + QWebSocket *pClient = qobject_cast(sender()); + qDebug() << "socketDisconnected:" << pClient; + if (pClient) { + pClient->deleteLater(); + } +} +void UserManagement::slot_timerTest() +{ + if(!pSocket) + return; + pSocket->sendTextMessage("[5,\"agl-identity-agent/event\",{\"event\":\"agl-identity-agent\/event\",\"data\":{\"eventName\":\"incoming\",\"accountid\":\"D2:D4:71:0D:B5:F1\",\"nickname\":\"D2:D4:71:0D:B5:F1\"},\"jtype\":\"afb-event\"}]"); + pSocket->sendTextMessage("[5,\"agl-identity-agent/event\",{\"event\":\"agl-identity-agent\/event\",\"data\":{\"eventName\":\"login\",\"accountid\":\"null\"},\"jtype\":\"afb-event\"}]"); +} +void UserManagement::onServerClosed() +{ + qWarning()<<"websocket server closed"; +} +#endif diff --git a/HomeScreen/src2/usermanagement.h b/HomeScreen/src2/usermanagement.h index 099c991..382d1ac 100644 --- a/HomeScreen/src2/usermanagement.h +++ b/HomeScreen/src2/usermanagement.h @@ -1,32 +1,85 @@ #ifndef USERMANAGEMENT_H #define USERMANAGEMENT_H +#define REAL_SERVER "ws://your_server.com:1234" + #include #include "applicationmodel.h" #include +#include #include +#ifndef REAL_SERVER +#include +#endif +struct User { + QString postal_address; + QPointF loc; + QString country; + QString mail; + QString city; + QString graphEmail; + QString graphPreferredLanguage; + QString ccNumberMasked; + QString ccExpYear; + QString ccExpMonth; + QString description; + QStringList groups; + QString last_name; + QString ccNumber; + QString house_identifier; + QString phone; + QString name; + QString state; + QString common_name; + QString fax; + QString postal_code; + QString first_name; + QString keytoken; +}; + class UserManagement : public QObject { Q_OBJECT public: - explicit UserManagement(QObject *home, QObject *shortcutArea, QObject *statusArea); + explicit UserManagement(QObject *root); signals: public slots: - void slot_timerTest(); + void connectWebsockets(); void onConnected(); void onClosed(); void onTextMessageReceived(QString message); + void onWebSocketError(QAbstractSocket::SocketError); + void slot_sendData(); +#ifndef REAL_SERVER + void onServerNewConnection(); + void onServerClosed(); + void processBinaryMessage(QByteArray message); + void processTextMessage(QString message); + void serverSocketDisconnected(); + void slot_timerTest(); +#endif private: QObject *home; QObject *shortcutArea; QObject *statusArea; + QObject *logo; + QByteArray data; ApplicationModel *appModel; - QTimer timerTest; - QString currentLanguage; QWebSocket webSocket; - void connectWebsockets(const QUrl &url); + int sequence; + bool jsonToMap(const QByteArray &buf, QVariantMap *map) const; + bool mapToJson(const QVariantMap &map, QByteArray *json) const; + bool jsonToList(const QByteArray &buf, QList *list) const; + bool listToJson(const QList &list, QByteArray *json) const; + void setUser(const User &user); +#ifndef REAL_SERVER + QTimer timerTest; + QWebSocket *pSocket; + QWebSocketServer *webSocketServer; + void launchServer(); +#endif }; #endif // USERMANAGEMENT_H -- cgit 1.2.3-korg