ADTF_DISPLAY_TOOLBOX  3.8.0 (ADTF 3.14.3)
Source Code for Demo Signal Provider
Location
./src/examples/src/example_signal_provider
This example shows:
  • how to configure and use the signal view.
Header
#pragma once
class cExampleSignalProvider : public ISignalRegistry::ISignalProvider::IEnabledSignals
{
public:
virtual ~cExampleSignalProvider();
tResult Init();
void Process(tTimeStamp tmCurrent);
// Inherited via IEnabledSignals
tResult EnableSignal(ISignalRegistry::tSignalID nSignalId) override;
tResult DisableSignal(ISignalRegistry::tSignalID nSignalId) override;
tResult AddSignal(ISignalRegistry::tSignalID& nSignalId,
const cString& strName,
const cString& strDescription = "",
const cString& strUnit = "",
tFloat64 nMin = 0,
tFloat64 nMax = 0,
tFloat64 nIncrement=1);
tResult AddSignalBatch(const cString& strPrefix, tSize nCount);
tResult RemoveSignal(ISignalRegistry::tSignalID nSignalId);
tSize GetNextSignalID();
private:
struct tSignal
{
tFloat64 nValue;
tFloat64 nIncrement;
};
object_ptr<ISignalRegistry::ISignalProvider> m_pProvider;
object_ptr<ISignalRegistry> m_pRegistry;
std::map<ISignalRegistry::tSignalID, tSignal> m_mapSignals;
std::mutex m_oEnabledSignalsMutex;
std::unordered_set<ISignalRegistry::tSignalID> m_oEnabledSignals;
};
/*
* This file depends on Qt which is licensed under LGPLv3.
* See ADTF_DIR/3rdparty/qt5 and doc/license for detailed information.
*/
#pragma once
class cExampleSignalProviderSrv : public cQtUIService, public IEventSink
{
public:
ADTF_CLASS_ID_NAME(cExampleSignalProviderSrv, "demo_signal_provider.ui_service.distb.cid", "Demo Signal Provider UI Service");
cExampleSignalProviderSrv();
tResult ServiceEvent(tInt nEventId,
tUInt32 ui32Param1 = 0,
tUInt32 ui32Param2 = 0,
tVoid* pvData = nullptr,
tInt szData = 0) override;
protected:
cProviderWidget* m_pWidget;
cExampleSignalProvider* m_pProvider;
object_ptr<IReferenceClock> m_pClock;
kernel_timer m_oTimer;
property_variable<tTimeStamp> m_tmProcessPeriod = 500000;
QWidget* CreateView() override;
tVoid ReleaseView() override;
tResult OnIdle() override;
private:
tResult InitView();
tVoid InitTimer();
// Inherited via IEventSink
tResult HandleEvent(const IEventSource& oSource, const tVoid* pvEventData) override;
};
/*
* This file depends on Qt which is licensed under LGPLv3.
* See ADTF_DIR/3rdparty/qt5 and doc/license for detailed information.
*/
#pragma once
class cProviderWidget : public QWidget
{
Q_OBJECT;
public slots:
void addSignalAccept();
void addSignalReject();
void removeSignalAccept();
void removeSignalReject();
void addSignalsAccept();
void addSignalsReject();
public:
explicit cProviderWidget(cExampleSignalProvider* oProvider);
~cProviderWidget();
void CreateAddSignalsDialog();
void CreateAddSignalDialog();
void CreateRemoveSignalDialog();
void ShowError(const cString& strMessage, const cString& strTitle = "Error occured");
void ShowMessage(const cString& strMessage, const cString& strTitle = "Message");
private:
cExampleSignalProvider *m_poProvider;
QPushButton* m_pButtonAdd;
QPushButton* m_pButtonRemove;
QPushButton* m_pButtonAddSignals;
QMessageBox* m_msgBox;
QDialog* m_pNewSignalDialog;
QDialog* m_pNewSignalsDialog;
QDialog* m_pRemoveSignalDialog;
QList<QLineEdit*> m_lstAddSignalFields;
QList<QLineEdit*> m_lstAddSignalsFields;
QList<QLineEdit*> m_lstRemoveFields;
};
Implementation
#include "stdafx.h"
#include "example_signal_provider.h"
#ifdef GetObject
#undef GetObject
#endif
#ifdef GetCurrentTime
#undef GetCurrentTime
#endif
tResult cExampleSignalProvider::EnableSignal(ISignalRegistry::tSignalID nSignalID)
{
std::lock_guard<std::mutex> oGuard(m_oEnabledSignalsMutex);
m_oEnabledSignals.insert(nSignalID);
RETURN_NOERROR;
}
tResult cExampleSignalProvider::DisableSignal(ISignalRegistry::tSignalID nSignalID)
{
std::lock_guard<std::mutex> oGuard(m_oEnabledSignalsMutex);
m_oEnabledSignals.erase(nSignalID);
RETURN_NOERROR;
}
tResult cExampleSignalProvider::AddSignal(ISignalRegistry::tSignalID& nSignalID,
const cString& strName,
const cString& strDescription,
const cString& strUnit,
tFloat64 nMin,
tFloat64 nMax,
tFloat64 nIncrement
)
{
nSignalID = GetNextSignalID();
RETURN_IF_FAILED(m_pProvider->AddSignal({ nSignalID, strName, strUnit, strDescription, nMin ,nMax }, this));
tSignal sSignal;
sSignal.nIncrement = nIncrement;
sSignal.nValue = 0;
m_mapSignals[nSignalID] = sSignal;
RETURN_NOERROR;
}
tResult cExampleSignalProvider::AddSignalBatch(const cString &strPrefix, tSize nCount)
{
for (tSize i = 0;i < nCount;++i)
{
tSize nNextId = GetNextSignalID();
cString strName = strPrefix + cString::ToStringFromType(nNextId, "%d");
tResult nResult = AddSignal(nNextId, strName,
"desc",
"kmh",
0,
100,
static_cast<tInt>(nNextId));
if (IS_FAILED(nResult))
{
RETURN_ERROR_DESC(ERR_FAILED, "Error creating signal %s", strName.GetPtr());
}
}
RETURN_NOERROR;
}
tSize cExampleSignalProvider::GetNextSignalID()
{
tSize nMaxId = 0;
for (const auto& a : m_mapSignals)
{
if (a.first > nMaxId)
{
nMaxId = a.first;
}
}
return nMaxId + 1;
}
tResult cExampleSignalProvider::RemoveSignal(ISignalRegistry::tSignalID nSignalID)
{
RETURN_IF_FAILED(m_pProvider->RemoveSignal(nSignalID));
m_mapSignals.erase(nSignalID);
RETURN_NOERROR;
}
tResult cExampleSignalProvider::Init()
{
RETURN_IF_FAILED(_runtime->GetObject(m_pRegistry));
RETURN_IF_FAILED(m_pRegistry->CreateProvider("signals", m_pProvider));
RETURN_NOERROR;
}
cExampleSignalProvider::~cExampleSignalProvider()
{
for (const auto &oSignal : m_mapSignals)
{
m_pProvider->RemoveSignal(oSignal.first);
}
m_mapSignals.clear();
}
void cExampleSignalProvider::Process(tTimeStamp tmCurrent)
{
for (const auto& oItem : m_mapSignals)
{
ISignalRegistry::tSignalID nSigID = oItem.first;
m_mapSignals[nSigID].nValue = m_mapSignals[nSigID].nValue + m_mapSignals[nSigID].nIncrement;
std::lock_guard<std::mutex> oGuard(m_oEnabledSignalsMutex);
if (m_oEnabledSignals.count(oItem.first))
{
// if enabled, update our signal value
m_pProvider->UpdateSignal(oItem.first, { tmCurrent, static_cast<tFloat64>(m_mapSignals[nSigID].nValue) });
}
}
}
/*
* This file depends on Qt which is licensed under LGPLv3.
* See ADTF_DIR/3rdparty/qt5 and doc/license for detailed information.
*/
#include "stdafx.h"
#include "example_signal_provider.h"
#include "provider_widget.h"
#include "example_signal_provider_srv.h"
ADTF_PLUGIN_VERSION("Demo Signal Provider Service Plugin",
disptb,
DISPTB_VERSION_MAJOR,
DISPTB_VERSION_MINOR,
DISPTB_VERSION_PATCH,
cExampleSignalProviderSrv)
#ifdef GetObject
#undef GetObject
#endif
#ifdef GetCurrentTime
#undef GetCurrentTime
#endif
cExampleSignalProviderSrv::cExampleSignalProviderSrv()
{
m_strTitle = cString("Example Signal Provider");
m_pWidget = nullptr;
_runtime->GetObject(m_pClock);
m_tmProcessPeriod.SetDescription("Signal update rate in [us]");
RegisterPropertyVariable("signal_update_rate", m_tmProcessPeriod);
SetDescription("Use this Service to add custom signals to ADTF Signal Registry and provide signals for Signal Scope and Table View.");
SetHelpLink("$(ADTF_DISPLAY_TOOLBOX_DIR)/doc/displaytoolbox_html/page_signal_provider_example_readme.html");
}
QWidget* cExampleSignalProviderSrv::CreateView()
{
m_pProvider = new cExampleSignalProvider();
if (IS_FAILED(m_pProvider->Init()))
{
LOG_ERROR("Failed to initialize ExampleSignalProvider");
return nullptr;
}
m_pWidget = new cProviderWidget(m_pProvider);
InitView();
return m_pWidget;
}
tVoid cExampleSignalProviderSrv::ReleaseView()
{
delete m_pWidget;
// In case jira issue "ACORE-9726" has been fixed, the workaround (below)
// can be removed.
#ifdef __GNUC__
// This is a workaround for a bug in adtf::base. Interface "IEnabledSignals" does not have a virtual dtor.
// We inherit from this interface, and try to delete the inherited class here.
// This gives a warning, which is treated as error. Thus we suppress the warning temporarily.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
#endif
delete m_pProvider;
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
m_oTimer.Stop();
m_pWidget = nullptr;
m_pProvider = nullptr;
}
tResult cExampleSignalProviderSrv::OnIdle()
{
RETURN_IF_POINTER_NULL(m_pWidget);
RETURN_NOERROR;
}
tVoid cExampleSignalProviderSrv::InitTimer()
{
m_oTimer = kernel_timer(adtf::services::IKernel::tTimerClock::ADTF,
adtf::services::IKernel::tSchedulingInfo(),
"example_signal_provider.timer",
m_tmProcessPeriod,
0,
[&]
{
const tTimeStamp tmCurrent = m_pClock->GetStreamTime();
m_pProvider->Process(tmCurrent);
});
}
tResult cExampleSignalProviderSrv::HandleEvent(const IEventSource & /*oSource*/, const tVoid * pvEventData)
{
const auto pEventInfo = static_cast<const IReferenceClock::tReferenceClockEvent*>(pvEventData);
if (pEventInfo->nEventId == IReferenceClock::EVENT_TimeResetEnd)
{
InitTimer();
}
else if (pEventInfo->nEventId == IReferenceClock::EVENT_TimeResetBegin)
{
m_oTimer.Stop();
}
RETURN_NOERROR;
}
tResult cExampleSignalProviderSrv::ServiceEvent(tInt nEventId,
tUInt32 ui32Param1,
tUInt32 ui32Param2,
tVoid* pvData,
tInt szData)
{
if (nEventId == IService::SE_ChangeRunLevel)
{
const tADTFRunLevel eLevel = static_cast<tADTFRunLevel>(ui32Param1);
if (ui32Param2 == IRuntime::CRLF_PostIncrementLevel)
{
if (eLevel == tADTFRunLevel::RL_Running)
{
auto pEventSource = ucom_cast<IEventSource*>(m_pClock.Get());
RETURN_IF_POINTER_NULL(pEventSource);
RETURN_IF_FAILED(pEventSource->RegisterEventSink(*this));
InitTimer();
}
}
else if (ui32Param2 == IRuntime::CRLF_PostDecrementLevel)
{
m_oTimer.Stop();
if (eLevel == tADTFRunLevel::RL_Running)
{
auto pEventSource = ucom_cast<IEventSource*>(m_pClock.Get());
RETURN_IF_POINTER_NULL(pEventSource);
RETURN_IF_FAILED(pEventSource->UnregisterEventSink(*this));
}
}
}
return cQtUIService::ServiceEvent(nEventId, ui32Param1, ui32Param2, pvData, szData);
}
tResult cExampleSignalProviderSrv::InitView()
{
RETURN_NOERROR;
}
/*
* This file depends on Qt which is licensed under LGPLv3.
* See ADTF_DIR/3rdparty/qt5 and doc/license for detailed information.
*/
#include "stdafx.h"
#include "example_signal_provider.h"
#include "provider_widget.h"
cProviderWidget::cProviderWidget(cExampleSignalProvider* pProvider) : m_poProvider(pProvider)
{
CreateAddSignalsDialog();
CreateAddSignalDialog();
CreateRemoveSignalDialog();
m_msgBox = new QMessageBox(this);
auto poGridLayout = new QGridLayout(this);
m_pButtonAdd = new QPushButton(this);
m_pButtonAdd->setText("Add Signal");
m_pButtonRemove = new QPushButton(this);
m_pButtonRemove->setText("Remove Signal");
m_pButtonAddSignals = new QPushButton(this);
m_pButtonAddSignals->setText("Add Signals");
poGridLayout->addWidget(m_pButtonAdd, 0, 0);
poGridLayout->addWidget(m_pButtonRemove, 1, 0);
poGridLayout->addWidget(m_pButtonAddSignals, 2, 0);
setLayout(poGridLayout);
QObject::connect(m_pButtonAdd, &QPushButton::clicked, [this]{ m_pNewSignalDialog->exec(); });
QObject::connect(m_pButtonRemove, &QPushButton::clicked, [this] { m_pRemoveSignalDialog->exec(); });
QObject::connect(m_pButtonAddSignals, &QPushButton::clicked, [this] { m_pNewSignalsDialog->exec(); });
}
cProviderWidget::~cProviderWidget()
{
}
void cProviderWidget::addSignalAccept()
{
tSize nId;
tResult nResult = m_poProvider->AddSignal(nId,
m_lstAddSignalFields.at(0)->text().toStdString().c_str(),
m_lstAddSignalFields.at(1)->text().toStdString().c_str(),
m_lstAddSignalFields.at(2)->text().toStdString().c_str(),
m_lstAddSignalFields.at(3)->text().toFloat(),
m_lstAddSignalFields.at(4)->text().toFloat(),
m_lstAddSignalFields.at(5)->text().toFloat());
m_pNewSignalDialog->hide();
if IS_FAILED(nResult)
{
ShowError("The signal could not be created");
}
ShowMessage(cString::Format("The signal was created with ID '%d'", nId).GetPtr());
}
void cProviderWidget::removeSignalAccept()
{
tSize nSignalID = m_lstRemoveFields.at(0)->text().toInt();
tResult nResult = m_poProvider->RemoveSignal(nSignalID);
m_pRemoveSignalDialog->hide();
if IS_FAILED(nResult)
{
ShowError(nResult.GetDescription());
}
}
void cProviderWidget::addSignalReject()
{
m_pNewSignalDialog->hide();
}
void cProviderWidget::removeSignalReject()
{
m_pRemoveSignalDialog->hide();
}
void cProviderWidget::addSignalsAccept()
{
m_pNewSignalsDialog->hide();
if (m_lstAddSignalsFields.at(0)->text().compare("minMaxBoth")==0)
{
ISignalRegistry::tSignalID nId;
const tResult nResult = m_poProvider->AddSignal(nId, "minMaxBoth", "desc", "kmh",
-std::numeric_limits<tFloat64>::max(),
std::numeric_limits<tFloat64>::max(), 1);
if IS_FAILED(nResult)
{
ShowError("Error creating signal. %s", nResult.GetDescription());
}
return;
}
else
{
tSize nSignalCount = m_lstAddSignalsFields.at(0)->text().toInt();
const tResult nResult = m_poProvider->AddSignalBatch(cString("batch/signal_"), nSignalCount);
if IS_FAILED(nResult)
{
ShowError("Error creating batch signals. %s", nResult.GetDescription());
}
}
}
void cProviderWidget::addSignalsReject()
{
m_pNewSignalsDialog->hide();
}
void cProviderWidget::ShowError(const cString &strMessage, const cString &strTitle)
{
m_msgBox->setText(strMessage.GetPtr());
m_msgBox->setWindowTitle(strTitle.GetPtr());
m_msgBox->show();
}
void cProviderWidget::ShowMessage(const cString & strMessage, const cString & strTitle)
{
ShowError(strMessage, strTitle);
}
void cProviderWidget::CreateAddSignalsDialog()
{
m_pNewSignalsDialog = new QDialog(this);
auto pForm = new QFormLayout(m_pNewSignalsDialog);
pForm->addRow(new QLabel("How many signals do you want to create?"));
const auto lineName = new QLineEdit(m_pNewSignalsDialog);
pForm->addRow("Number of signals:", lineName);
m_lstAddSignalsFields << lineName;
// Add some standard buttons (Cancel/Ok) at the bottom of the dialog
const auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
Qt::Horizontal, m_pNewSignalsDialog);
pForm->addRow(buttonBox);
QObject::connect(buttonBox, &QDialogButtonBox::accepted, this, &cProviderWidget::addSignalsAccept);
QObject::connect(buttonBox, &QDialogButtonBox::rejected, this, &cProviderWidget::addSignalsReject);
}
void cProviderWidget::CreateRemoveSignalDialog()
{
m_pRemoveSignalDialog = new QDialog(this);
auto pForm = new QFormLayout(m_pRemoveSignalDialog);
pForm->addRow(new QLabel("Specify signal to remove"));
const auto lineName = new QLineEdit(m_pRemoveSignalDialog);
pForm->addRow("Signal ID:", lineName);
m_lstRemoveFields << lineName;
// Add some standard buttons (Cancel/Ok) at the bottom of the dialog
const auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
Qt::Horizontal, m_pRemoveSignalDialog);
pForm->addRow(buttonBox);
QObject::connect(buttonBox, &QDialogButtonBox::accepted, this, &cProviderWidget::removeSignalAccept);
QObject::connect(buttonBox, &QDialogButtonBox::rejected, this, &cProviderWidget::removeSignalReject);
}
void cProviderWidget::CreateAddSignalDialog()
{
m_pNewSignalDialog = new QDialog(this);
auto pForm = new QFormLayout(m_pNewSignalDialog);
pForm->addRow(new QLabel("Specify signal to add"));
const auto lineName = new QLineEdit(m_pNewSignalDialog);
const auto lineDescription = new QLineEdit(m_pNewSignalDialog);
const auto lineUnit = new QLineEdit(m_pNewSignalDialog);
const auto lineMin = new QLineEdit(m_pNewSignalDialog);
const auto lineMax = new QLineEdit(m_pNewSignalDialog);
const auto lineIncrement = new QLineEdit(m_pNewSignalDialog);
pForm->addRow("Signal name:", lineName);
pForm->addRow("Signal description:", lineDescription);
pForm->addRow("Signal unit:", lineUnit);
pForm->addRow("Signal min:", lineMin);
pForm->addRow("Signal max:", lineMax);
pForm->addRow("Signal increment:", lineIncrement);
m_lstAddSignalFields << lineName;
m_lstAddSignalFields << lineDescription;
m_lstAddSignalFields << lineUnit;
m_lstAddSignalFields << lineMin;
m_lstAddSignalFields << lineMax;
m_lstAddSignalFields << lineIncrement;
const auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
Qt::Horizontal, m_pNewSignalDialog);
pForm->addRow(buttonBox);
QObject::connect(buttonBox, &QDialogButtonBox::accepted, this, &cProviderWidget::addSignalAccept);
QObject::connect(buttonBox, &QDialogButtonBox::rejected, this, &cProviderWidget::addSignalReject);
}
#include "moc_provider_widget.cpp"