Commit 4dc2b966 authored by Ionut Alexandrescu's avatar Ionut Alexandrescu

Add Azure-C-SDK integration

+ Requires the Azure-C-SDK package to be installed
+ Sends the events to the Azure IOT hub
parent 017266e3
#include "AzureConnection.h"
static void SendConfirmationCallback(IOTHUB_CLIENT_CONFIRMATION_RESULT result, void* userContextCallback)
{
Q_UNUSED(result)
EVENT_INSTANCE* eventInstance = (EVENT_INSTANCE*)userContextCallback;
IoTHubMessage_Destroy(eventInstance->messageHandle);
delete eventInstance;
}
static IOTHUBMESSAGE_DISPOSITION_RESULT ReceiveMessageCallback(IOTHUB_MESSAGE_HANDLE message, void* userContextCallback)
{
CAzureConnectionWorker* connection = (CAzureConnectionWorker*)userContextCallback;
IOTHUBMESSAGE_CONTENT_TYPE contentType = IoTHubMessage_GetContentType(message);
if (contentType == IOTHUBMESSAGE_BYTEARRAY)
{
const unsigned char* buffer = NULL;
size_t size = 0;
if (IoTHubMessage_GetByteArray(message, &buffer, &size) == IOTHUB_MESSAGE_OK)
{
connection->messageReceived( QByteArray((const char*)buffer,size));
}
}
return IOTHUBMESSAGE_ACCEPTED;
}
CAzureConnectionWorker::CAzureConnectionWorker(CAzureConnectionThread* thread)
: mIOTClientHandle(NULL)
, mMessageId(0)
, mConnectionThread(thread)
{
}
bool CAzureConnectionWorker::init(const QString& connectionString)
{
// Initialize
if (platform_init() != 0)
return false;
// Create the connection string
mIOTClientHandle = IoTHubClient_LL_CreateFromConnectionString(qPrintable(connectionString), AMQP_Protocol);
if (mIOTClientHandle == NULL)
return false;
// Register the receiving function
IOTHUB_CLIENT_RESULT receiveEvent = IoTHubClient_LL_SetMessageCallback(mIOTClientHandle, ReceiveMessageCallback, this);
if (receiveEvent != IOTHUB_CLIENT_OK)
return false;
return true;
}
bool CAzureConnectionWorker::sendMessage(const QByteArray& inMessage)
{
// Create the message
EVENT_INSTANCE* message = new EVENT_INSTANCE;
message->messageHandle = IoTHubMessage_CreateFromByteArray((const unsigned char*)inMessage.constData(), inMessage.size());
if (message->messageHandle == NULL)
return false;
message->messageTrackingId = mMessageId++;
IOTHUB_CLIENT_RESULT sendEvent = IoTHubClient_LL_SendEventAsync(mIOTClientHandle, message->messageHandle, SendConfirmationCallback, message);
if (sendEvent != IOTHUB_CLIENT_OK)
{
IoTHubMessage_Destroy(message->messageHandle);
delete message;
return false;
}
return true;
}
bool CAzureConnectionWorker::update()
{
IoTHubClient_LL_DoWork(mIOTClientHandle);
return true;
}
bool CAzureConnectionWorker::release()
{
IoTHubClient_LL_Destroy(mIOTClientHandle);
platform_deinit();
return true;
}
void CAzureConnectionWorker::messageReceived(const QByteArray& message)
{
if (mConnectionThread)
mConnectionThread->messageReceived(message);
}
/*************************************************************************************************/
/* CAzureConnectionThread */
/*************************************************************************************************/
CAzureConnectionThread::CAzureConnectionThread(const QString& connectionString)
: mConnectionString(connectionString)
, mRunning(true)
{
}
CAzureConnectionThread::~CAzureConnectionThread()
{
}
void CAzureConnectionThread::stopThread()
{
QMutexLocker lock(&mMutex);
mRunning = false;
}
bool CAzureConnectionThread::isRunning()
{
QMutexLocker lock(&mMutex);
return mRunning;
}
void CAzureConnectionThread::sendMessage(const QByteArray& message)
{
QMutexLocker lock(&mMutex);
if (mMessages.size() < 20)
mMessages.enqueue(message);
}
void CAzureConnectionThread::messageReceived(const QByteArray& message)
{
Q_EMIT(signalMessageReceived(message));
}
void CAzureConnectionThread::run()
{
CAzureConnectionWorker worker(this);
if (!worker.init(mConnectionString))
return;
unsigned long sleepTime = 1;
while (isRunning())
{
mMutex.lock();
if (mMessages.size() > 0)
{
worker.sendMessage(mMessages.dequeue());
}
mMutex.unlock();
worker.update();
QThread::msleep(sleepTime);
}
worker.release();
}
/*************************************************************************************************/
/* CAzureConnectionThread */
/*************************************************************************************************/
CAzureConnection::CAzureConnection()
: mThread( NULL )
{
}
CAzureConnection::~CAzureConnection()
{
}
void CAzureConnection::init( const QString& connectionString )
{
if ( mThread )
return;
mThread = new CAzureConnectionThread(connectionString);
QObject::connect(mThread, &CAzureConnectionThread::signalMessageReceived,
this, &CAzureConnection::signalMessageReceived, Qt::QueuedConnection);
mThread->start();
}
void CAzureConnection::release()
{
if (mThread)
{
mThread->stopThread();
mThread->wait();
delete mThread;
}
mThread = NULL;
}
void CAzureConnection::slotSendMessage(const QByteArray& inMessage)
{
if (mThread)
mThread->sendMessage(inMessage);
}
#ifndef AZURECONNECTION_H
#define AZURECONNECTION_H
#include <stdio.h>
#include <stdlib.h>
#include "azure_c_shared_utility/platform.h"
#include "azure_c_shared_utility/threadapi.h"
#include "azure_c_shared_utility/crt_abstractions.h"
#include "azure_c_shared_utility/shared_util_options.h"
#include "iothub_client.h"
#include "iothub_client_options.h"
#include "iothub_message.h"
#include "iothubtransportamqp.h"
#include <QString>
#include <QObject>
#include <QThread>
#include <QMutex>
#include <QQueue>
#include <QMutexLocker>
typedef struct EVENT_INSTANCE_TAG
{
IOTHUB_MESSAGE_HANDLE messageHandle;
size_t messageTrackingId; // For tracking the messages within the user callback.
} EVENT_INSTANCE;
class CAzureConnectionThread;
class CAzureConnectionWorker
{
public:
explicit CAzureConnectionWorker(CAzureConnectionThread* thread);
bool init(const QString& connectionString);
bool sendMessage(const QByteArray& inMessage);
bool update();
bool release();
void messageReceived(const QByteArray& message);
private:
IOTHUB_CLIENT_LL_HANDLE mIOTClientHandle;
size_t mMessageId;
CAzureConnectionThread* mConnectionThread;
};
//-------------------------------------------------------------------------------------------------
class CAzureConnectionThread : public QThread
{
Q_OBJECT
public:
explicit CAzureConnectionThread( const QString& connectionString );
~CAzureConnectionThread();
void stopThread();
void sendMessage( const QByteArray& message );
void messageReceived( const QByteArray& message );
Q_SIGNALS:
void signalMessageReceived(const QByteArray& message);
protected:
void run() override;
private:
bool isRunning();
QString mConnectionString;
QMutex mMutex;
bool mRunning;
QQueue<QByteArray> mMessages;
};
//-------------------------------------------------------------------------------------------------
class CAzureConnection : public QObject
{
Q_OBJECT
public:
CAzureConnection();
~CAzureConnection();
void init( const QString& connectionString );
void release();
public Q_SLOTS:
void slotSendMessage(const QByteArray& message);
Q_SIGNALS:
void signalMessageReceived(const QByteArray& message);
private:
CAzureConnectionThread* mThread;
};
#endif // AZURECONNECTION_H
#include "AzureEvent.h"
#include <QtCore/QJsonObject>
#include <QtCore/QJsonDocument>
#include <QtCore/QStandardPaths>
#include <QtCore/QFile>
CAzureEvent::CAzureEvent()
: mCost( 0 )
, mCharging( 0 )
, mCounter( 0 )
{
}
float CAzureEvent::cost()
{
return mCost;
}
void CAzureEvent::setCost( float cost )
{
mCost = cost;
sendEvent();
}
QString CAzureEvent::userName()
{
return mUserName;
}
void CAzureEvent::setUserName( QString str )
{
mUserName = str;
sendEvent();
}
void CAzureEvent::setCharging( float charge )
{
mCharging = charge;
sendEvent();
}
float CAzureEvent::charging()
{
return mCharging;
}
void CAzureEvent::resetAll()
{
mUserName.clear();
mCharging = 0;
mCost = 0;
sendEvent();
}
void CAzureEvent::sendEvent()
{
QJsonObject jobject;
jobject["Id"] = QString::number( mCounter );
jobject["UserName"] = mUserName;
jobject["TotalCost"] = QString::number( mCost );
jobject["Charging"] = QString::number( mCharging );
mCounter++;
QJsonDocument doc( jobject );
Q_EMIT(signalSendEvent(doc.toJson()));
}
#ifndef AZUREEVENT_H
#define AZUREEVENT_H
#include <QObject>
class CAzureEvent : public QObject
{
Q_OBJECT
Q_PROPERTY( QString userName READ userName WRITE setUserName NOTIFY userNameChanged)
Q_PROPERTY( float cost READ cost WRITE setCost NOTIFY costChanged )
Q_PROPERTY( float charging READ charging WRITE setCharging NOTIFY chargingChanged )
public:
CAzureEvent( );
float cost();
void setCost( float cost );
QString userName();
void setUserName( QString str );
float charging();
void setCharging( float charge );
Q_INVOKABLE void sendEvent();
Q_INVOKABLE void resetAll();
Q_SIGNALS:
void userNameChanged();
void costChanged();
void chargingChanged();
void signalSendEvent(const QByteArray&);
public:
QString mUserName;
float mCost;
float mCharging;
int mCounter;
};
#endif // AZUREEVENT_H
......@@ -2,7 +2,8 @@ QT += qml quick multimedia
CONFIG += c++11
SOURCES += main.cpp \
TranslationSelect.cpp
TranslationSelect.cpp \
AzureEvent.cpp
RESOURCES += qml.qrc
......@@ -23,6 +24,44 @@ TRANSLATIONS += Translation/DemoQtWS_fr.ts
TRANSLATIONS += Translation/DemoQtWS_de.ts
TRANSLATIONS += Translation/DemoQtWS_it.ts
AZURE_PATH = C:/Development/Azure-IOT-ARM/azure-iot-sdk-c
equals(TEMPLATE,"vcapp"):exists($$AZURE_PATH) {
message("Building with Azure")
CONFIG(debug, debug|release) {
AZURE_BUILD = Debug
} else {
AZURE_BUILD = Release
}
deployFiles.files += $${AZURE_PATH}/iothub_client/$${AZURE_BUILD}/iothub_client_dll.dll
INSTALLS += deployFiles
LIBS += $${AZURE_PATH}/iothub_client/$${AZURE_BUILD}/iothub_client.lib
LIBS += $${AZURE_PATH}/iothub_client/$${AZURE_BUILD}/iothub_client_amqp_transport.lib
LIBS += $${AZURE_PATH}/iothub_client/$${AZURE_BUILD}/iothub_client_http_transport.lib
LIBS += $${AZURE_PATH}/iothub_client/$${AZURE_BUILD}/iothub_client_amqp_ws_transport.lib
LIBS += $${AZURE_PATH}/iothub_client/$${AZURE_BUILD}/iothub_client_mqtt_transport.lib
LIBS += $${AZURE_PATH}/iothub_client/$${AZURE_BUILD}/iothub_client_mqtt_ws_transport.lib
LIBS += $${AZURE_PATH}/umqtt/$${AZURE_BUILD}/umqtt.lib
LIBS += $${AZURE_PATH}/c-utility/$${AZURE_BUILD}/aziotsharedutil.lib
LIBS += $${AZURE_PATH}/uamqp/$${AZURE_BUILD}/uamqp.lib
INCLUDEPATH += $${AZURE_PATH}/iothub_client/../deps/parson
INCLUDEPATH += $${AZURE_PATH}/deps/uhttp/deps/c-utility/inc
INCLUDEPATH += $${AZURE_PATH}/iothub_client/inc
INCLUDEPATH += $${AZURE_PATH}/uamqp/inc
INCLUDEPATH += $${AZURE_PATH}/umqtt/inc
SOURCES += AzureConnection.cpp
HEADERS += AzureConnection.h
DEFINES += DEF_USE_AZURE
}
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
......@@ -36,7 +75,8 @@ else: unix:!android: target.path = /opt/$${TARGET}/bin
DISTFILES +=
HEADERS += \
TranslationSelect.h
TranslationSelect.h \
AzureEvent.h
qtPrepareTool(LRELEASE, lrelease)
for(tsfile, TRANSLATIONS) {
......
......@@ -50,17 +50,16 @@ Dial {
uniform sampler2D src;
uniform lowp float qt_Opacity;
uniform lowp float angle;
void main()
{
float pixelAngle = atan( coord.y - 0.5, coord.x - 0.5 );
if ( ( pixelAngle > angle ) || ( pixelAngle < -2.44346 ) || ( pixelAngle > 2.44346 ) )
void main() {
lowp float pixelAngleTan = atan( coord.y - 0.5, coord.x - 0.5 );
if ( ( pixelAngleTan > angle ) || ( pixelAngleTan < -2.44346 ) || ( pixelAngleTan > 2.44346 ) )
{
gl_FragColor = vec4( 0, 0,0, 0);
}
else
{
lowp vec4 tex0 = texture2D(src, coord);
gl_FragColor = tex0 * qt_Opacity;
gl_FragColor = texture2D(src, coord) * qt_Opacity;
}
}"
......
......@@ -64,6 +64,7 @@ Page {
onChargedPercentageChanged :
{
updateSpinBoxes( chargedPercentage )
azureEvent.charging = chargedPercentage;
}
onSignalChargeCompleted:
......
......@@ -3,6 +3,12 @@
#include <QQmlContext>
#include <QFontDatabase>
#include "TranslationSelect.h"
#include "AzureEvent.h"
#ifdef DEF_USE_AZURE
#include "AzureConnection.h"
#endif
static const char* connectionString = "";
int main(int argc, char *argv[])
{
......@@ -30,6 +36,14 @@ int main(int argc, char *argv[])
QQmlApplicationEngine engine;
TranslationSelect translation;
engine.rootContext()->setContextProperty( "translation", (QObject*)&translation);
CAzureEvent aev;
engine.rootContext()->setContextProperty( "azureEvent", (QObject*)&aev);
#ifdef DEF_USE_AZURE
CAzureConnection connection;
connection.init(connectionString);
QObject::connect(&aev, &CAzureEvent::signalSendEvent,
&connection, &CAzureConnection::slotSendMessage);
#endif
#if ( QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) )
QObject::connect( &translation, &TranslationSelect::languageChanged,
......@@ -39,5 +53,9 @@ int main(int argc, char *argv[])
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
int rep = app.exec();
#ifdef DEF_USE_AZURE
connection.release();
#endif
return rep;
}
......@@ -125,6 +125,7 @@ ApplicationWindow {
pageChargeSelect.initializeValues();
pagePayment.initializeValues();
infoPopup.setDescription( 0 )
azureEvent.resetAll();
break;
case 1: // PageAutentification
footerItem.leftButtonVisible = 1
......@@ -134,6 +135,7 @@ ApplicationWindow {
infoPopup.setDescription( 1 )
break;
case 2: // PageChargeSelect
azureEvent.userName = "test";
pagePayment.initializeValues();
footerItem.leftButtonVisible = 1
footerItem.leftButtonEnabled = 1
......@@ -142,6 +144,7 @@ ApplicationWindow {
infoPopup.setDescription( 2 )
break;
case 3: // PagePayment
azureEvent.charging = Variables.initialCharge;
footerItem.leftButtonVisible = 1
footerItem.leftButtonEnabled = 1
footerItem.rightButtonVisible = 1
......@@ -149,6 +152,7 @@ ApplicationWindow {
infoPopup.setDescription( 3 )
break;
case 4: // PageChargeConfirm
azureEvent.cost = Variables.currentPrice;
footerItem.leftButtonVisible = 0
footerItem.leftButtonEnabled = 0
footerItem.rightButtonVisible = 1
......@@ -166,6 +170,7 @@ ApplicationWindow {
Component.onCompleted:
{
translation.languageChanged.connect(updateText);
azureEvent.sendEvent();
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment