fixed conversions added shared data layer
This commit is contained in:
parent
238efba31c
commit
078b5f0522
@ -118,26 +118,23 @@ void IntegrationPluginKeba::setupThing(ThingSetupInfo *info)
|
||||
|
||||
if (thing->thingClassId() == wallboxThingClassId) {
|
||||
|
||||
if(!m_udpSocket){
|
||||
m_udpSocket = new QUdpSocket(this);
|
||||
if (!m_udpSocket->bind(QHostAddress::AnyIPv4, 7090, QAbstractSocket::DefaultForPlatform)) {
|
||||
qCWarning(dcKebaKeContact()) << "Cannot bind to port" << 7090;
|
||||
if(!m_kebaData){
|
||||
qCDebug(dcKebaKeContact()) << "Creating new Keba data layer";
|
||||
m_kebaData = new KeContactDataLayer;
|
||||
if (!m_kebaData->init()) {
|
||||
m_kebaData->deleteLater();
|
||||
return info->finish(Thing::ThingErrorHardwareNotAvailable, QT_TR_NOOP("Error opening network port."));
|
||||
}
|
||||
}
|
||||
|
||||
QHostAddress address = QHostAddress(thing->paramValue(wallboxThingIpAddressParamTypeId).toString());
|
||||
KeContact *keba = new KeContact(address, m_udpSocket, m_udpSocket);
|
||||
KeContact *keba = new KeContact(address, m_kebaData, m_kebaData);
|
||||
connect(keba, &KeContact::reachableChanged, this, &IntegrationPluginKeba::onConnectionChanged);
|
||||
connect(keba, &KeContact::commandExecuted, this, &IntegrationPluginKeba::onCommandExecuted);
|
||||
connect(keba, &KeContact::reportTwoReceived, this, &IntegrationPluginKeba::onReportTwoReceived);
|
||||
connect(keba, &KeContact::reportThreeReceived, this, &IntegrationPluginKeba::onReportThreeReceived);
|
||||
connect(keba, &KeContact::report1XXReceived, this, &IntegrationPluginKeba::onReport1XXReceived);
|
||||
connect(keba, &KeContact::broadcastReceived, this, &IntegrationPluginKeba::onBroadcastReceived);
|
||||
if (!keba->init()){
|
||||
keba->deleteLater();
|
||||
return info->finish(Thing::ThingErrorHardwareNotAvailable, QT_TR_NOOP("Error opening network port."));
|
||||
}
|
||||
|
||||
keba->getReport1();
|
||||
connect(keba, &KeContact::reportOneReceived, info, [info, this, keba] (const KeContact::ReportOne &report) {
|
||||
@ -146,13 +143,13 @@ void IntegrationPluginKeba::setupThing(ThingSetupInfo *info)
|
||||
qCDebug(dcKebaKeContact()) << "Report one received for" << thing->name();
|
||||
qCDebug(dcKebaKeContact()) << " - Firmware" << report.firmware;
|
||||
qCDebug(dcKebaKeContact()) << " - Product" << report.product;
|
||||
qCDebug(dcKebaKeContact()) << " - Uptime" << report.seconds;
|
||||
qCDebug(dcKebaKeContact()) << " - Uptime" << report.seconds/60 << "[min]";
|
||||
qCDebug(dcKebaKeContact()) << " - Com Module" << report.comModule;
|
||||
|
||||
thing->setStateValue(wallboxConnectedStateTypeId, true);
|
||||
thing->setStateValue(wallboxFirmwareStateTypeId, report.firmware);
|
||||
thing->setStateValue(wallboxModelStateTypeId, report.product);
|
||||
thing->setStateValue(wallboxUptimeStateTypeId, report.seconds);
|
||||
thing->setStateValue(wallboxUptimeStateTypeId, report.seconds/60);
|
||||
|
||||
m_kebaDevices.insert(thing->id(), keba);
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
@ -174,7 +171,7 @@ void IntegrationPluginKeba::postSetupThing(Thing *thing)
|
||||
qCWarning(dcKebaKeContact()) << "Thing class id not supported" << thing->thingClassId();
|
||||
return;
|
||||
}
|
||||
|
||||
thing->setStateValue(wallboxConnectedStateTypeId, true);
|
||||
KeContact *keba = m_kebaDevices.value(thing->id());
|
||||
if (!keba) {
|
||||
qCWarning(dcKebaKeContact()) << "No Keba connection found for this thing";
|
||||
@ -227,9 +224,8 @@ void IntegrationPluginKeba::thingRemoved(Thing *thing)
|
||||
|
||||
if (myThings().empty()) {
|
||||
qCDebug(dcKebaKeContact()) << "Closing UDP Ports";
|
||||
m_udpSocket->close();
|
||||
m_udpSocket->deleteLater();
|
||||
m_udpSocket = nullptr;
|
||||
m_kebaData->deleteLater();
|
||||
m_kebaData = nullptr;
|
||||
|
||||
qCDebug(dcKebaKeContact()) << "Stopping plugin timers";
|
||||
hardwareManager()->pluginTimerManager()->unregisterTimer(m_reconnectTimer);
|
||||
@ -344,7 +340,7 @@ void IntegrationPluginKeba::onReportTwoReceived(const KeContact::ReportTwo &repo
|
||||
qCDebug(dcKebaKeContact()) << " - Output:" << reportTwo.output;
|
||||
qCDebug(dcKebaKeContact()) << " - Input:" << reportTwo.input;
|
||||
qCDebug(dcKebaKeContact()) << " - Serial number:" << reportTwo.serialNumber;
|
||||
qCDebug(dcKebaKeContact()) << " - Uptime:" << reportTwo.seconds;
|
||||
qCDebug(dcKebaKeContact()) << " - Uptime:" << reportTwo.seconds/60 << "[min]";
|
||||
|
||||
if (reportTwo.serialNumber == thing->stateValue(wallboxSerialnumberStateTypeId).toString()) {
|
||||
setDeviceState(thing, reportTwo.state);
|
||||
@ -353,14 +349,16 @@ void IntegrationPluginKeba::onReportTwoReceived(const KeContact::ReportTwo &repo
|
||||
thing->setStateValue(wallboxPowerStateTypeId, reportTwo.enableUser);
|
||||
thing->setStateValue(wallboxError1StateTypeId, reportTwo.error1);
|
||||
thing->setStateValue(wallboxError2StateTypeId, reportTwo.error2);
|
||||
//thing->setStateValue(wallboxMaxChargingCurrentAmpereStateTypeId, reportTwo.maxCurrent);
|
||||
thing->setStateValue(wallboxSystemEnabledStateTypeId, reportTwo.enableSys);
|
||||
|
||||
thing->setStateValue(wallboxMaxChargingCurrentStateTypeId, reportTwo.maxCurrent);
|
||||
thing->setStateValue(wallboxMaxChargingCurrentPercentStateTypeId, reportTwo.maxCurrentPercentage);
|
||||
//thing->setStateValue(wallboxCurrentHardwareLimitationStateTypeId, reportTwo.currentHardwareLimitation);
|
||||
thing->setStateValue(wallboxMaxPossibleChargingCurrentStateTypeId, reportTwo.currentHardwareLimitation);
|
||||
|
||||
thing->setStateValue(wallboxOutputX2StateTypeId, reportTwo.output);
|
||||
thing->setStateValue(wallboxInputStateTypeId, reportTwo.input);
|
||||
|
||||
thing->setStateValue(wallboxUptimeStateTypeId, reportTwo.seconds);
|
||||
thing->setStateValue(wallboxUptimeStateTypeId, reportTwo.seconds/60);
|
||||
} else {
|
||||
qCWarning(dcKebaKeContact()) << "Received report but the serial number didn't match";
|
||||
}
|
||||
@ -374,17 +372,17 @@ void IntegrationPluginKeba::onReportThreeReceived(const KeContact::ReportThree &
|
||||
return;
|
||||
|
||||
qCDebug(dcKebaKeContact()) << "Report 3 received for" << thing->name() << "Serial number:" << thing->stateValue(wallboxSerialnumberStateTypeId).toString();
|
||||
qCDebug(dcKebaKeContact()) << " - Current phase 1:" << reportThree.currentPhase1 << "[mA]";
|
||||
qCDebug(dcKebaKeContact()) << " - Current phase 2:" << reportThree.currentPhase2 << "[mA]";
|
||||
qCDebug(dcKebaKeContact()) << " - Current phase 3:" << reportThree.currentPhase3 << "[mA]";
|
||||
qCDebug(dcKebaKeContact()) << " - Current phase 1:" << reportThree.currentPhase1 << "[A]";
|
||||
qCDebug(dcKebaKeContact()) << " - Current phase 2:" << reportThree.currentPhase2 << "[A]";
|
||||
qCDebug(dcKebaKeContact()) << " - Current phase 3:" << reportThree.currentPhase3 << "[A]";
|
||||
qCDebug(dcKebaKeContact()) << " - Voltage phase 1:" << reportThree.voltagePhase1 << "[V]";
|
||||
qCDebug(dcKebaKeContact()) << " - Voltage phase 2:" << reportThree.voltagePhase2 << "[V]";
|
||||
qCDebug(dcKebaKeContact()) << " - Voltage phase 3:" << reportThree.voltagePhase3 << "[V]";
|
||||
qCDebug(dcKebaKeContact()) << " - Power consumption:" << reportThree.power << "[W]";
|
||||
qCDebug(dcKebaKeContact()) << " - Energy session" << reportThree.energySession << "[Wh]";
|
||||
qCDebug(dcKebaKeContact()) << " - Energy total" << reportThree.energyTotal << "[Wh]";
|
||||
qCDebug(dcKebaKeContact()) << " - Power consumption:" << reportThree.power << "[kW]";
|
||||
qCDebug(dcKebaKeContact()) << " - Energy session" << reportThree.energySession << "[kWh]";
|
||||
qCDebug(dcKebaKeContact()) << " - Energy total" << reportThree.energyTotal << "[kWh]";
|
||||
qCDebug(dcKebaKeContact()) << " - Serial number" << reportThree.serialNumber;
|
||||
qCDebug(dcKebaKeContact()) << " - Uptime" << reportThree.seconds;
|
||||
qCDebug(dcKebaKeContact()) << " - Uptime" << reportThree.seconds/60 << "[min]";
|
||||
|
||||
if (reportThree.serialNumber == thing->stateValue(wallboxSerialnumberStateTypeId).toString()) {
|
||||
thing->setStateValue(wallboxCurrentPhase1EventTypeId, reportThree.currentPhase1);
|
||||
@ -483,7 +481,7 @@ void IntegrationPluginKeba::onBroadcastReceived(KeContact::BroadcastType type, c
|
||||
setDeviceState(thing, KeContact::State(content.toInt()));
|
||||
break;
|
||||
case KeContact::BroadcastTypeMaxCurr:
|
||||
thing->setStateValue(wallboxMaxChargingCurrentStateTypeId, content.toInt());
|
||||
thing->setStateValue(wallboxMaxChargingCurrentStateTypeId, content.toInt()/1000.00);
|
||||
break;
|
||||
case KeContact::BroadcastTypeEnableSys:
|
||||
qCDebug(dcKebaKeContact()) << "Broadcast enable sys not implemented";
|
||||
@ -503,30 +501,28 @@ void IntegrationPluginKeba::executeAction(ThingActionInfo *info)
|
||||
return info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
}
|
||||
|
||||
QUuid requestId;
|
||||
if(action.actionTypeId() == wallboxMaxChargingCurrentActionTypeId){
|
||||
int milliAmpere = action.param(wallboxMaxChargingCurrentActionMaxChargingCurrentParamTypeId).value().toInt();
|
||||
QUuid requestId = keba->setMaxAmpere(milliAmpere);
|
||||
m_asyncActions.insert(requestId, info);
|
||||
connect(info, &ThingActionInfo::aborted, this, [requestId, this]{m_asyncActions.remove(requestId);});
|
||||
requestId = keba->setMaxAmpere(milliAmpere);
|
||||
|
||||
} else if(action.actionTypeId() == wallboxPowerActionTypeId){
|
||||
QUuid requestId = keba->enableOutput(action.param(wallboxPowerActionTypeId).value().toBool());
|
||||
m_asyncActions.insert(requestId, info);
|
||||
connect(info, &ThingActionInfo::aborted, this, [requestId, this]{m_asyncActions.remove(requestId);});
|
||||
requestId = keba->enableOutput(action.param(wallboxPowerActionTypeId).value().toBool());
|
||||
|
||||
} else if(action.actionTypeId() == wallboxDisplayActionTypeId){
|
||||
QUuid requestId = keba->displayMessage(action.param(wallboxDisplayActionMessageParamTypeId).value().toByteArray());
|
||||
m_asyncActions.insert(requestId, info);
|
||||
connect(info, &ThingActionInfo::aborted, this, [requestId, this]{m_asyncActions.remove(requestId);});
|
||||
requestId = keba->displayMessage(action.param(wallboxDisplayActionMessageParamTypeId).value().toByteArray());
|
||||
|
||||
} else if(action.actionTypeId() == wallboxOutputX2ActionTypeId){
|
||||
} else if(action.actionTypeId() == wallboxOutputX2ActionTypeId) {
|
||||
requestId = keba->setOutputX2(action.param(wallboxOutputX2ActionOutputX2ParamTypeId).value().toBool());
|
||||
|
||||
} else if(action.actionTypeId() == wallboxFailsafeModeActionTypeId){
|
||||
|
||||
requestId = keba->setFailsafe(60, 0, false);
|
||||
} else {
|
||||
qCWarning(dcKebaKeContact()) << "Unhandled ActionTypeId:" << action.actionTypeId();
|
||||
info->finish(Thing::ThingErrorActionTypeNotFound);
|
||||
return info->finish(Thing::ThingErrorActionTypeNotFound);
|
||||
}
|
||||
m_asyncActions.insert(requestId, info);
|
||||
connect(info, &ThingActionInfo::aborted, this, [requestId, this]{m_asyncActions.remove(requestId);});
|
||||
} else {
|
||||
qCWarning(dcKebaKeContact()) << "Execute action, unhandled device class" << thing->thingClass();
|
||||
info->finish(Thing::ThingErrorThingClassNotFound);
|
||||
|
||||
@ -34,6 +34,7 @@
|
||||
#include "integrations/integrationplugin.h"
|
||||
#include "plugintimer.h"
|
||||
#include "kecontact.h"
|
||||
#include "kecontactdatalayer.h"
|
||||
#include "discovery.h"
|
||||
#include "host.h"
|
||||
|
||||
@ -66,7 +67,7 @@ private:
|
||||
PluginTimer *m_updateTimer = nullptr;
|
||||
PluginTimer *m_reconnectTimer = nullptr;
|
||||
|
||||
QUdpSocket *m_udpSocket = nullptr;
|
||||
KeContactDataLayer *m_kebaData = nullptr;
|
||||
|
||||
Discovery *m_discovery = nullptr;
|
||||
QHash<ThingId, KeContact *> m_kebaDevices;
|
||||
|
||||
@ -83,14 +83,7 @@
|
||||
"type": "QString",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"id": "1d30ce60-2ea0-450f-817e-5c88f59ebfbf",
|
||||
"name": "sessionId",
|
||||
"displayName": "Session ID",
|
||||
"displayNameEvent": "Session ID changed",
|
||||
"type": "uint",
|
||||
"defaultValue": ""
|
||||
},
|
||||
|
||||
{
|
||||
"id": "83ed0774-2a91-434d-b03c-d920d02f2981",
|
||||
"name": "power",
|
||||
@ -130,9 +123,9 @@
|
||||
"name": "current",
|
||||
"displayName": "Current",
|
||||
"displayNameEvent": "Current changed",
|
||||
"type": "int",
|
||||
"type": "double",
|
||||
"unit": "Ampere",
|
||||
"defaultValue": 0
|
||||
"defaultValue": 0.00
|
||||
},
|
||||
{
|
||||
"id": "593656f0-babf-4308-8767-68f34e10fb15",
|
||||
@ -140,11 +133,11 @@
|
||||
"displayName": "Maximal charging current",
|
||||
"displayNameEvent": "Maximal charging current changed",
|
||||
"displayNameAction": "Set maximal charging current",
|
||||
"type": "uint",
|
||||
"unit": "MilliAmpere",
|
||||
"defaultValue": 6,
|
||||
"minValue": 6000,
|
||||
"maxValue": 63000,
|
||||
"type": "double",
|
||||
"unit": "Ampere",
|
||||
"defaultValue": 6.00,
|
||||
"minValue": 6.00,
|
||||
"maxValue": 63.00,
|
||||
"writable": true
|
||||
},
|
||||
{
|
||||
@ -199,9 +192,9 @@
|
||||
"name": "currentPhase1",
|
||||
"displayName": "Current phase 1",
|
||||
"displayNameEvent": "Current phase 1 changed",
|
||||
"type": "int",
|
||||
"type": "double",
|
||||
"unit": "Ampere",
|
||||
"defaultValue": 0
|
||||
"defaultValue": 0.00
|
||||
},
|
||||
{
|
||||
"id": "cdc7e10a-0d0a-4e93-ad2c-d34ffca45c97",
|
||||
@ -210,7 +203,7 @@
|
||||
"displayNameEvent": "Current phase 2 changed",
|
||||
"type": "double",
|
||||
"unit": "Ampere",
|
||||
"defaultValue": 0
|
||||
"defaultValue": 0.00
|
||||
},
|
||||
{
|
||||
"id": "da838dc8-85f0-4e55-b4b5-cb93a43b373d",
|
||||
@ -219,7 +212,7 @@
|
||||
"displayNameEvent": "Current phase 3 changed",
|
||||
"type": "double",
|
||||
"unit": "Ampere",
|
||||
"defaultValue": 0
|
||||
"defaultValue": 0.00
|
||||
},
|
||||
{
|
||||
"id": "7af9e93b-099d-4d9d-a480-9c0f66aecd8b",
|
||||
@ -228,7 +221,7 @@
|
||||
"displayNameEvent": "Power consumtion changed",
|
||||
"type": "double",
|
||||
"unit": "KiloWatt",
|
||||
"defaultValue": 0
|
||||
"defaultValue": 0.00
|
||||
},
|
||||
{
|
||||
"id": "889c3c9a-96b4-4408-bd9a-d79e36ed9296",
|
||||
@ -239,6 +232,14 @@
|
||||
"unit": "Percentage",
|
||||
"defaultValue": 0.00
|
||||
},
|
||||
{
|
||||
"id": "1d30ce60-2ea0-450f-817e-5c88f59ebfbf",
|
||||
"name": "sessionId",
|
||||
"displayName": "Session ID",
|
||||
"displayNameEvent": "Session ID changed",
|
||||
"type": "uint",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"id": "a6f35ea0-aaea-438b-b818-6d161762611e",
|
||||
"name": "sessionTime",
|
||||
@ -290,7 +291,7 @@
|
||||
"displayName": "Uptime",
|
||||
"displayNameEvent": "Uptime changed",
|
||||
"type": "int",
|
||||
"unit": "Seconds",
|
||||
"unit": "Minutes",
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
@ -338,7 +339,7 @@
|
||||
"name": "duration",
|
||||
"displayName": "Duration",
|
||||
"type": "int",
|
||||
"unit": "Seconds",
|
||||
"unit": "Minutes",
|
||||
"defaultValue": 0
|
||||
},
|
||||
{
|
||||
|
||||
@ -9,9 +9,11 @@ SOURCES += \
|
||||
kecontact.cpp \
|
||||
discovery.cpp \
|
||||
host.cpp \
|
||||
kecontactdatalayer.cpp
|
||||
|
||||
HEADERS += \
|
||||
integrationpluginkeba.h \
|
||||
kecontact.h \
|
||||
discovery.h \
|
||||
host.h \
|
||||
kecontactdatalayer.h
|
||||
|
||||
@ -34,11 +34,12 @@
|
||||
#include <QJsonDocument>
|
||||
|
||||
|
||||
KeContact::KeContact(const QHostAddress &address, QUdpSocket *udpSocket, QObject *parent) :
|
||||
KeContact::KeContact(const QHostAddress &address, KeContactDataLayer *dataLayer, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_udpSocket(udpSocket),
|
||||
m_dataLayer(dataLayer),
|
||||
m_address(address)
|
||||
{
|
||||
qCDebug(dcKebaKeContact()) << "Creating KeContact connection for address" << m_address;
|
||||
m_requestTimeoutTimer = new QTimer(this);
|
||||
m_requestTimeoutTimer->setSingleShot(true);
|
||||
connect(m_requestTimeoutTimer, &QTimer::timeout, this, [this] {
|
||||
@ -48,23 +49,15 @@ KeContact::KeContact(const QHostAddress &address, QUdpSocket *udpSocket, QObject
|
||||
handleNextCommandInQueue();
|
||||
m_deviceBlocked = false;
|
||||
});
|
||||
|
||||
connect(m_dataLayer, &KeContactDataLayer::datagramReceived, this, &KeContact::onReceivedDatagram);
|
||||
}
|
||||
|
||||
KeContact::~KeContact() {
|
||||
KeContact::~KeContact()
|
||||
{
|
||||
qCDebug(dcKebaKeContact()) << "Deleting KeContact connection for address" << m_address;
|
||||
}
|
||||
|
||||
bool KeContact::init(){
|
||||
qCDebug(dcKebaKeContact()) << "Initializing Keba connection";
|
||||
if(m_udpSocket){
|
||||
connect(m_udpSocket, &QUdpSocket::readyRead, this, &KeContact::readPendingDatagrams);
|
||||
} else {
|
||||
qCWarning(dcKebaKeContact()) << "UDP socket not valid";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QHostAddress KeContact::address()
|
||||
{
|
||||
return m_address;
|
||||
@ -105,13 +98,12 @@ void KeContact::sendCommand(const QByteArray &command, const QUuid &requestId)
|
||||
emit commandExecuted(requestId, false);
|
||||
}
|
||||
});
|
||||
|
||||
sendCommand(command);
|
||||
}
|
||||
|
||||
void KeContact::sendCommand(const QByteArray &command)
|
||||
{
|
||||
if (!m_udpSocket) {
|
||||
if (!m_dataLayer) {
|
||||
qCWarning(dcKebaKeContact()) << "UDP socket not initialized";
|
||||
emit reachableChanged(false);
|
||||
return;
|
||||
@ -121,8 +113,8 @@ void KeContact::sendCommand(const QByteArray &command)
|
||||
//add command to queue
|
||||
m_commandList.append(command);
|
||||
} else {
|
||||
//send command
|
||||
m_udpSocket->writeDatagram(command, m_address, m_port);
|
||||
qCDebug(dcKebaKeContact()) << "Writing datagram" << command << m_address;
|
||||
m_dataLayer->write( m_address, command);
|
||||
m_requestTimeoutTimer->start(5000);
|
||||
m_deviceBlocked = true;
|
||||
}
|
||||
@ -130,8 +122,8 @@ void KeContact::sendCommand(const QByteArray &command)
|
||||
|
||||
void KeContact::handleNextCommandInQueue()
|
||||
{
|
||||
if (!m_udpSocket) {
|
||||
qCWarning(dcKebaKeContact()) << "UDP socket not initialized";
|
||||
if (!m_dataLayer) {
|
||||
qCWarning(dcKebaKeContact()) << "Data layer not initialized";
|
||||
if (m_reachable == true) {
|
||||
m_reachable = false;
|
||||
emit reachableChanged(false);
|
||||
@ -141,10 +133,9 @@ void KeContact::handleNextCommandInQueue()
|
||||
qCDebug(dcKebaKeContact()) << "Handle Command Queue- Pending commands" << m_commandList.length() << "Pending requestIds" << m_pendingRequests.length();
|
||||
if (!m_commandList.isEmpty()) {
|
||||
QByteArray command = m_commandList.takeFirst();
|
||||
m_udpSocket->writeDatagram(command, m_address, m_port);
|
||||
qCDebug(dcKebaKeContact()) << "Writing datagram" << command << m_address;
|
||||
m_dataLayer->write( m_address, command);
|
||||
m_requestTimeoutTimer->start(5000);
|
||||
} else {
|
||||
//nothing to do
|
||||
}
|
||||
}
|
||||
|
||||
@ -256,6 +247,17 @@ void KeContact::getReport1XX(int reportNumber)
|
||||
getReport(reportNumber);
|
||||
}
|
||||
|
||||
QUuid KeContact::setOutputX2(bool state)
|
||||
{
|
||||
QUuid requestId = QUuid::createUuid();
|
||||
m_pendingRequests.append(requestId);
|
||||
QByteArray data;
|
||||
data.append("output "+QVariant((state ? 1 : 0)).toByteArray());
|
||||
qCDebug(dcKebaKeContact()) << "Set Output X2, state:" << state << "Command:" << data;
|
||||
sendCommand(data, requestId);
|
||||
return requestId;
|
||||
}
|
||||
|
||||
void KeContact::getReport(int reportNumber)
|
||||
{
|
||||
QByteArray data;
|
||||
@ -275,170 +277,159 @@ QUuid KeContact::unlockCharger()
|
||||
return requestId;
|
||||
}
|
||||
|
||||
void KeContact::readPendingDatagrams()
|
||||
void KeContact::onReceivedDatagram(const QHostAddress &address, const QByteArray &datagram)
|
||||
{
|
||||
QUdpSocket *socket= qobject_cast<QUdpSocket*>(sender());
|
||||
if (address != m_address) {
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray datagram;
|
||||
QHostAddress sender;
|
||||
quint16 senderPort;
|
||||
if(datagram.contains("TCH-OK")){
|
||||
|
||||
while (socket->hasPendingDatagrams()) {
|
||||
//Command response has been received, now send the next command
|
||||
m_deviceBlocked = false;
|
||||
m_requestTimeoutTimer->stop();
|
||||
handleNextCommandInQueue();
|
||||
|
||||
if (sender != m_address) {
|
||||
//Only process data from the target device
|
||||
continue;
|
||||
}
|
||||
|
||||
datagram.resize(socket->pendingDatagramSize());
|
||||
socket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
|
||||
qCDebug(dcKebaKeContact()) << "Data received" << datagram;
|
||||
|
||||
if (m_reachable != true) {
|
||||
m_reachable = true;
|
||||
emit reachableChanged(true);
|
||||
}
|
||||
|
||||
if(datagram.contains("TCH-OK")){
|
||||
|
||||
//Command response has been received, now send the next command
|
||||
m_deviceBlocked = false;
|
||||
m_requestTimeoutTimer->stop();
|
||||
handleNextCommandInQueue();
|
||||
|
||||
if (!m_pendingRequests.isEmpty()) {
|
||||
QUuid requestId = m_pendingRequests.takeFirst();
|
||||
if (datagram.contains("done")) {
|
||||
emit commandExecuted(requestId, true);
|
||||
} else {
|
||||
emit commandExecuted(requestId, false);
|
||||
}
|
||||
if (!m_pendingRequests.isEmpty()) {
|
||||
QUuid requestId = m_pendingRequests.takeFirst();
|
||||
if (datagram.contains("done")) {
|
||||
emit commandExecuted(requestId, true);
|
||||
} else {
|
||||
//Probably the response has taken too long and the requestId has been already removed
|
||||
}
|
||||
} else if(datagram.left(8).contains("Firmware")){
|
||||
|
||||
//Command response has been received, now send the next command
|
||||
m_deviceBlocked = false;
|
||||
m_requestTimeoutTimer->stop();
|
||||
handleNextCommandInQueue();
|
||||
|
||||
qCDebug(dcKebaKeContact()) << "Firmware information reveiced";
|
||||
QByteArrayList firmware = datagram.split(':');
|
||||
if (firmware.length() >= 2) {
|
||||
emit deviceInformationReceived(firmware[1]);
|
||||
emit commandExecuted(requestId, false);
|
||||
}
|
||||
} else {
|
||||
//Probably the response has taken too long and the requestId has been already removed
|
||||
}
|
||||
} else if(datagram.left(8).contains("Firmware")){
|
||||
|
||||
//Command response has been received, now send the next command
|
||||
m_deviceBlocked = false;
|
||||
m_requestTimeoutTimer->stop();
|
||||
handleNextCommandInQueue();
|
||||
//Command response has been received, now send the next command
|
||||
m_deviceBlocked = false;
|
||||
m_requestTimeoutTimer->stop();
|
||||
handleNextCommandInQueue();
|
||||
|
||||
// Convert the rawdata to a json document
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(datagram, &error);
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qCWarning(dcKebaKeContact()) << "Failed to parse JSON data" << datagram << ":" << error.errorString();
|
||||
qCDebug(dcKebaKeContact()) << "Firmware information reveiced";
|
||||
QByteArrayList firmware = datagram.split(':');
|
||||
if (firmware.length() >= 2) {
|
||||
emit deviceInformationReceived(firmware[1]);
|
||||
}
|
||||
} else {
|
||||
|
||||
//Command response has been received, now send the next command
|
||||
m_deviceBlocked = false;
|
||||
m_requestTimeoutTimer->stop();
|
||||
handleNextCommandInQueue();
|
||||
|
||||
// Convert the rawdata to a json document
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(datagram, &error);
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
qCWarning(dcKebaKeContact()) << "Failed to parse JSON data" << datagram << ":" << error.errorString();
|
||||
}
|
||||
|
||||
QVariantMap data = jsonDoc.toVariant().toMap();
|
||||
|
||||
if(data.contains("ID")) {
|
||||
int id = data.value("ID").toInt();
|
||||
if (id == 1) {
|
||||
ReportOne reportOne;
|
||||
qCDebug(dcKebaKeContact()) << "Report 1 received";
|
||||
reportOne.product = data.value("Product").toString();
|
||||
reportOne.firmware = data.value("Firmware").toString();
|
||||
reportOne.serialNumber = data.value("Serial").toString();
|
||||
//"Backend:"
|
||||
//"timeQ": 3
|
||||
//"DIP-Sw1": "0x22"
|
||||
//"DIP-Sw2":
|
||||
if (data.contains("COM-module")) {
|
||||
reportOne.comModule = (data.value("COM-module").toInt() == 1);
|
||||
} else {
|
||||
reportOne.comModule = false;
|
||||
}
|
||||
if (data.contains("Sec")) {
|
||||
reportOne.comModule = data.value("Sec").toInt();
|
||||
} else {
|
||||
reportOne.comModule = 0;
|
||||
}
|
||||
emit reportOneReceived(reportOne);
|
||||
|
||||
} else if (id == 2) {
|
||||
|
||||
ReportTwo reportTwo;
|
||||
qCDebug(dcKebaKeContact()) << "Report 2 received";
|
||||
int state = data.value("State").toInt();
|
||||
reportTwo.state = State(state);
|
||||
reportTwo.error1 = data.value("Error1").toInt();
|
||||
reportTwo.error2 = data.value("Error2").toInt();
|
||||
reportTwo.plugState = PlugState(data.value("Plug").toInt());
|
||||
reportTwo.enableUser = data.value("Enable user").toBool();
|
||||
reportTwo.enableSys = data.value("Enable sys").toBool();
|
||||
reportTwo.maxCurrent = data.value("Max curr").toInt()/1000.00;
|
||||
reportTwo.maxCurrentPercentage = data.value("Max curr %").toInt()/10.00;
|
||||
reportTwo.currentHardwareLimitation = data.value("Curr HW").toInt()/1000.00;
|
||||
reportTwo.currentUser = data.value("Curr user").toInt()/1000.00;
|
||||
reportTwo.currentFailsafe = data.value("Curr FS").toInt()/1000.00;
|
||||
reportTwo.timeoutFailsafe = data.value("Tmo FS").toInt();
|
||||
reportTwo.setEnergy = data.value("Setenergy").toInt()/10000.00;
|
||||
reportTwo.output = data.value("Output").toInt();
|
||||
reportTwo.input= data.value("Input").toInt();
|
||||
reportTwo.serialNumber = data.value("Serial").toString();
|
||||
reportTwo.seconds = data.value("Sec").toInt();
|
||||
// Not documented:
|
||||
//"AuthON": 0
|
||||
//"Authreq": 0
|
||||
emit reportTwoReceived(reportTwo);
|
||||
|
||||
} else if (id == 3) {
|
||||
|
||||
ReportThree reportThree;
|
||||
qCDebug(dcKebaKeContact()) << "Report 3 reveiced";
|
||||
reportThree.currentPhase1 = data.value("I1").toInt()/1000.00;
|
||||
reportThree.currentPhase2 = data.value("I2").toInt()/1000.00;
|
||||
reportThree.currentPhase3 = data.value("I3").toInt()/1000.00;
|
||||
reportThree.voltagePhase1 = data.value("U1").toInt();
|
||||
reportThree.voltagePhase2 = data.value("U2").toInt();
|
||||
reportThree.voltagePhase3 = data.value("U3").toInt();
|
||||
reportThree.power = data.value("P").toInt()/1000.00;
|
||||
reportThree.powerFactor = data.value("PF").toInt()/10.00;
|
||||
reportThree.energySession = data.value("E pres").toInt()/10000.00;
|
||||
reportThree.energyTotal = data.value("E total").toInt()/10000.00;
|
||||
reportThree.serialNumber = data.value("Serial").toString();
|
||||
reportThree.seconds = data.value("Sec").toInt();
|
||||
emit reportThreeReceived(reportThree);
|
||||
} else if (id >= 100) {
|
||||
|
||||
Report1XX report;
|
||||
report.sessionId = data.value("Session ID").toInt();
|
||||
report.currHW = data.value("Curr HW").toInt();
|
||||
report.startTime = data.value("E Start ").toInt()/10000.00;
|
||||
report.presentEnergy = data.value("E Pres ").toInt()/10000.00;
|
||||
report.startTime = data.value("started[s]").toInt();
|
||||
report.endTime = data.value("ended[s] ").toInt();
|
||||
report.stopReason = data.value("reason ").toInt();
|
||||
report.rfidTag = data.value("RFID tag").toByteArray();
|
||||
report.rfidClass = data.value("RFID class").toByteArray();
|
||||
report.serialNumber = data.value("Serial").toString();
|
||||
report.seconds = data.value("Sec").toInt();
|
||||
emit report1XXReceived(id, report);
|
||||
}
|
||||
|
||||
QVariantMap data = jsonDoc.toVariant().toMap();
|
||||
|
||||
if(data.contains("ID")) {
|
||||
int id = data.value("ID").toInt();
|
||||
if (id == 1) {
|
||||
ReportOne reportOne;
|
||||
qCDebug(dcKebaKeContact()) << "Report 1 received";
|
||||
reportOne.product = data.value("Product").toString();
|
||||
reportOne.firmware = data.value("Firmware").toString();
|
||||
reportOne.serialNumber = data.value("Serial").toString();
|
||||
if (data.contains("COM-module")) {
|
||||
reportOne.comModule = (data.value("COM-module").toInt() == 1);
|
||||
} else {
|
||||
reportOne.comModule = false;
|
||||
}
|
||||
if (data.contains("Sec")) {
|
||||
reportOne.comModule = data.value("Sec").toInt();
|
||||
} else {
|
||||
reportOne.comModule = 0;
|
||||
}
|
||||
emit reportOneReceived(reportOne);
|
||||
|
||||
} else if (id == 2) {
|
||||
|
||||
ReportTwo reportTwo;
|
||||
qCDebug(dcKebaKeContact()) << "Report 2 received";
|
||||
int state = data.value("State").toInt();
|
||||
reportTwo.state = State(state);
|
||||
reportTwo.error1 = data.value("Error1").toInt();
|
||||
reportTwo.error2 = data.value("Error2").toInt();
|
||||
reportTwo.plugState = PlugState(data.value("Plug").toInt());
|
||||
reportTwo.enableUser = data.value("Enable user").toBool();
|
||||
reportTwo.enableSys = data.value("Enable sys").toBool();
|
||||
reportTwo.maxCurrent = data.value("Max curr").toInt()/1000;
|
||||
reportTwo.maxCurrentPercentage = data.value("Max curr %").toInt()/10;
|
||||
reportTwo.currentHardwareLimitation = data.value("Curr HW").toInt()/1000;
|
||||
reportTwo.currentUser = data.value("Curr user").toInt();
|
||||
reportTwo.currentFailsafe = data.value("Curr FS").toInt();
|
||||
reportTwo.timeoutFailsafe = data.value("Tmo FS").toInt();
|
||||
reportTwo.output = data.value("Output").toInt();
|
||||
reportTwo.input= data.value("Input").toInt();
|
||||
reportTwo.serialNumber = data.value("Serial").toString();
|
||||
reportTwo.seconds = data.value("Sec").toInt();
|
||||
emit reportTwoReceived(reportTwo);
|
||||
|
||||
} else if (id == 3) {
|
||||
|
||||
ReportThree reportThree;
|
||||
qCDebug(dcKebaKeContact()) << "Report 3 reveiced";
|
||||
reportThree.currentPhase1 = data.value("I1").toInt()/1000.00;
|
||||
reportThree.currentPhase2 = data.value("I2").toInt()/1000.00;
|
||||
reportThree.currentPhase3 = data.value("I3").toInt()/1000.00;
|
||||
reportThree.voltagePhase1 = data.value("U1").toInt();
|
||||
reportThree.voltagePhase2 = data.value("U2").toInt();
|
||||
reportThree.voltagePhase3 = data.value("U3").toInt();
|
||||
reportThree.power = data.value("P").toInt()/1000.00;
|
||||
reportThree.powerFactor = data.value("PF").toInt()/10.00;
|
||||
reportThree.energySession = data.value("E pres").toInt()/10000.00;
|
||||
reportThree.energyTotal = data.value("E total").toInt()/10000.00;
|
||||
reportThree.serialNumber = data.value("Serial").toString();
|
||||
reportThree.seconds = data.value("Sec").toInt();
|
||||
emit reportThreeReceived(reportThree);
|
||||
} else if (id >= 100) {
|
||||
|
||||
Report1XX report;
|
||||
report.sessionId = data.value("Session ID").toInt();
|
||||
report.currHW = data.value("Curr HW").toInt();
|
||||
report.startTime = data.value("E Start ").toInt()/10000.00;
|
||||
report.presentEnergy = data.value("E Pres ").toInt()/10000.00;
|
||||
report.startTime = data.value("started[s]").toInt();
|
||||
report.endTime = data.value("ended[s] ").toInt();
|
||||
report.stopReason = data.value("reason ").toInt();
|
||||
report.rfidTag = data.value("RFID tag").toByteArray();
|
||||
report.rfidClass = data.value("RFID class").toByteArray();
|
||||
report.serialNumber = data.value("Serial").toString();
|
||||
report.seconds = data.value("Sec").toInt();
|
||||
emit report1XXReceived(id, report);
|
||||
}
|
||||
} else {
|
||||
if (data.contains("State")) {
|
||||
emit broadcastReceived(BroadcastType::BroadcastTypeState, data.value("State"));
|
||||
}
|
||||
if (data.contains("Plug")) {
|
||||
emit broadcastReceived(BroadcastType::BroadcastTypePlug, data.value("Plug"));
|
||||
}
|
||||
if (data.contains("Input")) {
|
||||
emit broadcastReceived(BroadcastType::BroadcastTypeInput, data.value("Input"));
|
||||
}
|
||||
if (data.contains("Enable sys")) {
|
||||
emit broadcastReceived(BroadcastType::BroadcastTypeEnableSys, data.value("Enable sys"));
|
||||
}
|
||||
if (data.contains("Max curr")) {
|
||||
emit broadcastReceived(BroadcastType::BroadcastTypeMaxCurr, data.value("Max curr"));
|
||||
}
|
||||
if (data.contains("E pres")) {
|
||||
emit broadcastReceived(BroadcastType::BroadcastTypeEPres, data.value("E pres"));
|
||||
}
|
||||
} else {
|
||||
if (data.contains("State")) {
|
||||
emit broadcastReceived(BroadcastType::BroadcastTypeState, data.value("State"));
|
||||
}
|
||||
if (data.contains("Plug")) {
|
||||
emit broadcastReceived(BroadcastType::BroadcastTypePlug, data.value("Plug"));
|
||||
}
|
||||
if (data.contains("Input")) {
|
||||
emit broadcastReceived(BroadcastType::BroadcastTypeInput, data.value("Input"));
|
||||
}
|
||||
if (data.contains("Enable sys")) {
|
||||
emit broadcastReceived(BroadcastType::BroadcastTypeEnableSys, data.value("Enable sys"));
|
||||
}
|
||||
if (data.contains("Max curr")) {
|
||||
emit broadcastReceived(BroadcastType::BroadcastTypeMaxCurr, data.value("Max curr"));
|
||||
}
|
||||
if (data.contains("E pres")) {
|
||||
emit broadcastReceived(BroadcastType::BroadcastTypeEPres, data.value("E pres"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,11 +38,13 @@
|
||||
#include <QUdpSocket>
|
||||
#include <QUuid>
|
||||
|
||||
#include "kecontactdatalayer.h"
|
||||
|
||||
class KeContact : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit KeContact(const QHostAddress &address, QUdpSocket *udpSocket, QObject *parent = nullptr);
|
||||
explicit KeContact(const QHostAddress &address, KeContactDataLayer *dataLayer, QObject *parent = nullptr);
|
||||
~KeContact();
|
||||
bool init();
|
||||
|
||||
@ -90,15 +92,15 @@ public:
|
||||
PlugState plugState; //Current condition of the loading connection
|
||||
bool enableSys; //Enable state for charging (contains Enable input, RFID, UDP,..).
|
||||
bool enableUser; //Enable condition via UDP.
|
||||
int maxCurrent; //Current preset value via Control pilot in milliampere.
|
||||
int maxCurrentPercentage; //Current preset value via Control pilot in 0,1% of the PWM value
|
||||
int currentHardwareLimitation; //Highest possible charging current of the charging connection. Contains device maximum, DIP-switch setting, cable coding and temperature reduction.
|
||||
int currentUser; //Current preset value of the user via UDP; Default = 63000mA.
|
||||
int currentFailsafe; //Current preset value for the Failsafe function.
|
||||
double maxCurrent; //Current preset value via Control pilot in ampere.
|
||||
double maxCurrentPercentage; //Current preset value via Control pilot in 0,1% of the PWM value
|
||||
double currentHardwareLimitation; //Highest possible charging current of the charging connection. Contains device maximum, DIP-switch setting, cable coding and temperature reduction.
|
||||
double currentUser; //Current preset value of the user via UDP; Default = 63000mA.
|
||||
double currentFailsafe; //Current preset value for the Failsafe function.
|
||||
int timeoutFailsafe; //Communication timeout before triggering the Failsafe function.
|
||||
int currTimer; //Shows the current preset value of currtime.
|
||||
int timeoutCt; //Shows the remaining time until the current value is accepted.
|
||||
int setEnergy; //Shows the set energy limit
|
||||
double setEnergy; //Shows the set energy limit
|
||||
bool output; //State of the output X2.
|
||||
bool input; //State of the potential free Enable input X1. When using the input, please pay attention to the information in the installation manual.
|
||||
QString serialNumber; //Serial number
|
||||
@ -113,23 +115,23 @@ public:
|
||||
double currentPhase2; //current in A
|
||||
double currentPhase3; //current in A
|
||||
double power; //Current power in W (Real Power).
|
||||
double powerFactor; //Power factor in 0,1% (cosphi)
|
||||
double energySession; //Power consumption of the current loading session in 0,1Wh; Reset with new loading session (state = 2).
|
||||
double energyTotal; //Total power consumption (persistent) without current loading session 0,1Wh; Is summed up after each completed charging session (state = 0).
|
||||
double powerFactor; //Power factor (cosphi)
|
||||
double energySession; //Power consumption of the current loading session in kWh; Reset with new loading session (state = 2).
|
||||
double energyTotal; //Total power consumption (persistent) without current loading session kWh; Is summed up after each completed charging session (state = 0).
|
||||
QString serialNumber;
|
||||
int seconds; //Current system clock since restart of the charging station.
|
||||
};
|
||||
|
||||
struct Report1XX {
|
||||
int sessionId; // running session counter; not resettable"
|
||||
int currHW; // maximum charging current of the cable and the charging station setting (equal to report 2)"E
|
||||
double currHW; // maximum charging current of the cable and the charging station setting
|
||||
double startEnergy; // total energy value at the beginning of the session"
|
||||
double presentEnergy; // delivered energy until now (equal to E pres in report 3)"
|
||||
int startTime; // system time when the session was started (seconds from reboot; NTP implementation is still under progress)"
|
||||
int startTime; // system time when the session was started (seconds from reboot;
|
||||
int endTime; // system time when the session has ended"
|
||||
int stopReason; // reason for stopping the session (1 = vehicle unplug; 10 = Rfid token)"
|
||||
QByteArray rfidTag; // RFID Token ID if session started with rfid; hexadecimal; first character is the lowest nibble"
|
||||
QByteArray rfidClass; // RFID classifier shows the defined color code if the used card is a BMW card (for example “010104” means the white card)"
|
||||
QByteArray rfidTag; // RFID Token ID if session started with rfid
|
||||
QByteArray rfidClass; // RFID classifier shows the defined color code
|
||||
QString serialNumber; // serial number of the charging station"
|
||||
int seconds; // current time when the report was generated
|
||||
};
|
||||
@ -156,12 +158,12 @@ public:
|
||||
void getReport1XX(int reportNumber = 100); // Command “report 1xx”
|
||||
|
||||
// Command “currtime”
|
||||
// Command “output”
|
||||
QUuid setOutputX2(bool state); // Command “output”
|
||||
|
||||
private:
|
||||
int m_port = 7090;
|
||||
KeContactDataLayer *m_dataLayer;
|
||||
bool m_reachable = false;
|
||||
QUdpSocket *m_udpSocket = nullptr;
|
||||
|
||||
QHostAddress m_address;
|
||||
QByteArrayList m_commandList;
|
||||
bool m_deviceBlocked = false;
|
||||
@ -171,8 +173,8 @@ private:
|
||||
QList<QUuid> m_pendingRequests;
|
||||
|
||||
void getReport(int reportNumber);
|
||||
void sendCommand(const QByteArray &data, const QUuid &requestId);
|
||||
void sendCommand(const QByteArray &data);
|
||||
void sendCommand(const QByteArray &command, const QUuid &requestId);
|
||||
void sendCommand(const QByteArray &command);
|
||||
void handleNextCommandInQueue();
|
||||
|
||||
signals:
|
||||
@ -186,7 +188,7 @@ signals:
|
||||
void broadcastReceived(BroadcastType type, const QVariant &content);
|
||||
|
||||
private slots:
|
||||
void readPendingDatagrams();
|
||||
void onReceivedDatagram(const QHostAddress &address, const QByteArray &datagram);
|
||||
};
|
||||
#endif // KECONTACT_H
|
||||
|
||||
|
||||
39
keba/kecontactdatalayer.cpp
Normal file
39
keba/kecontactdatalayer.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
#include "kecontactdatalayer.h"
|
||||
#include "extern-plugininfo.h"
|
||||
|
||||
KeContactDataLayer::KeContactDataLayer(QObject *parent) : QObject(parent)
|
||||
{
|
||||
m_udpSocket = new QUdpSocket(this);
|
||||
connect(m_udpSocket, &QUdpSocket::readyRead, this, &KeContactDataLayer::readPendingDatagrams);
|
||||
}
|
||||
|
||||
bool KeContactDataLayer::init()
|
||||
{
|
||||
if (!m_udpSocket->bind(QHostAddress::AnyIPv4, m_port, QAbstractSocket::ShareAddress)) {
|
||||
qCWarning(dcKebaKeContact()) << "Cannot bind to port" << m_port;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void KeContactDataLayer::write(const QHostAddress &address, const QByteArray &data)
|
||||
{
|
||||
m_udpSocket->writeDatagram(data, address, m_port);
|
||||
}
|
||||
|
||||
void KeContactDataLayer::readPendingDatagrams()
|
||||
{
|
||||
QUdpSocket *socket= qobject_cast<QUdpSocket*>(sender());
|
||||
|
||||
QByteArray datagram;
|
||||
QHostAddress senderAddress;
|
||||
quint16 senderPort;
|
||||
|
||||
while (socket->hasPendingDatagrams()) {
|
||||
|
||||
datagram.resize(socket->pendingDatagramSize());
|
||||
socket->readDatagram(datagram.data(), datagram.size(), &senderAddress, &senderPort);
|
||||
qCDebug(dcKebaKeContact()) << "Data received" << datagram << senderAddress;
|
||||
emit datagramReceived(senderAddress, datagram);
|
||||
}
|
||||
}
|
||||
27
keba/kecontactdatalayer.h
Normal file
27
keba/kecontactdatalayer.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef KECONTACTDATALAYER_H
|
||||
#define KECONTACTDATALAYER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QUdpSocket>
|
||||
|
||||
class KeContactDataLayer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit KeContactDataLayer(QObject *parent = nullptr);
|
||||
bool init();
|
||||
|
||||
void write(const QHostAddress &address, const QByteArray &data);
|
||||
|
||||
private:
|
||||
int m_port = 7090;
|
||||
QUdpSocket *m_udpSocket = nullptr;
|
||||
|
||||
signals:
|
||||
void datagramReceived(const QHostAddress &address, const QByteArray &data);
|
||||
|
||||
private slots:
|
||||
void readPendingDatagrams();
|
||||
};
|
||||
|
||||
#endif // KECONTACTDATALAYER_H
|
||||
Loading…
x
Reference in New Issue
Block a user