multi keba bug fixed
This commit is contained in:
parent
5b38c6c9bc
commit
396804bbd5
@ -52,7 +52,14 @@ void IntegrationPluginKeba::init()
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
foreach (Thing *existingThing, myThings()) {
|
foreach (Thing *existingThing, myThings()) {
|
||||||
if (existingThing->paramValue(wallboxThingMacAddressParamTypeId).toString() == host.macAddress()) {
|
if (existingThing->paramValue(wallboxThingMacAddressParamTypeId).toString().isEmpty()) {
|
||||||
|
//This device got probably manually setup, to enable auto rediscovery the MAC address needs to setup
|
||||||
|
if (existingThing->paramValue(wallboxThingIpAddressParamTypeId).toString() == host.address()) {
|
||||||
|
qCDebug(dcKebaKeContact()) << "Keba Wallbox MAC Address has been discovered" << existingThing->name() << host.macAddress();
|
||||||
|
existingThing->setParamValue(wallboxThingMacAddressParamTypeId, host.macAddress());
|
||||||
|
|
||||||
|
}
|
||||||
|
} else if (existingThing->paramValue(wallboxThingMacAddressParamTypeId).toString() == host.macAddress()) {
|
||||||
if (existingThing->paramValue(wallboxThingIpAddressParamTypeId).toString() != host.address()) {
|
if (existingThing->paramValue(wallboxThingIpAddressParamTypeId).toString() != host.address()) {
|
||||||
qCDebug(dcKebaKeContact()) << "Keba Wallbox IP Address has changed, from" << existingThing->paramValue(wallboxThingIpAddressParamTypeId).toString() << "to" << host.address();
|
qCDebug(dcKebaKeContact()) << "Keba Wallbox IP Address has changed, from" << existingThing->paramValue(wallboxThingIpAddressParamTypeId).toString() << "to" << host.address();
|
||||||
existingThing->setParamValue(wallboxThingIpAddressParamTypeId, host.address());
|
existingThing->setParamValue(wallboxThingIpAddressParamTypeId, host.address());
|
||||||
@ -109,8 +116,16 @@ void IntegrationPluginKeba::setupThing(ThingSetupInfo *info)
|
|||||||
|
|
||||||
if (thing->thingClassId() == wallboxThingClassId) {
|
if (thing->thingClassId() == wallboxThingClassId) {
|
||||||
|
|
||||||
|
if(!m_udpSocket){
|
||||||
|
m_udpSocket = new QUdpSocket(this);
|
||||||
|
if (!m_udpSocket->bind(QHostAddress::AnyIPv4, 7090, QAbstractSocket::ShareAddress)) {
|
||||||
|
qCWarning(dcKebaKeContact()) << "Cannot bind to port" << 7090;
|
||||||
|
return info->finish(Thing::ThingErrorHardwareNotAvailable, QT_TR_NOOP("Error opening network port."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QHostAddress address = QHostAddress(thing->paramValue(wallboxThingIpAddressParamTypeId).toString());
|
QHostAddress address = QHostAddress(thing->paramValue(wallboxThingIpAddressParamTypeId).toString());
|
||||||
KeContact *keba = new KeContact(address, this);
|
KeContact *keba = new KeContact(address, m_udpSocket, m_udpSocket);
|
||||||
connect(keba, &KeContact::reachableChanged, this, &IntegrationPluginKeba::onConnectionChanged);
|
connect(keba, &KeContact::reachableChanged, this, &IntegrationPluginKeba::onConnectionChanged);
|
||||||
connect(keba, &KeContact::commandExecuted, this, &IntegrationPluginKeba::onCommandExecuted);
|
connect(keba, &KeContact::commandExecuted, this, &IntegrationPluginKeba::onCommandExecuted);
|
||||||
connect(keba, &KeContact::reportTwoReceived, this, &IntegrationPluginKeba::onReportTwoReceived);
|
connect(keba, &KeContact::reportTwoReceived, this, &IntegrationPluginKeba::onReportTwoReceived);
|
||||||
@ -118,7 +133,6 @@ void IntegrationPluginKeba::setupThing(ThingSetupInfo *info)
|
|||||||
connect(keba, &KeContact::report1XXReceived, this, &IntegrationPluginKeba::onReport1XXReceived);
|
connect(keba, &KeContact::report1XXReceived, this, &IntegrationPluginKeba::onReport1XXReceived);
|
||||||
connect(keba, &KeContact::broadcastReceived, this, &IntegrationPluginKeba::onBroadcastReceived);
|
connect(keba, &KeContact::broadcastReceived, this, &IntegrationPluginKeba::onBroadcastReceived);
|
||||||
if (!keba->init()){
|
if (!keba->init()){
|
||||||
qCWarning(dcKebaKeContact()) << "Cannot bind to port" << 7090;
|
|
||||||
keba->deleteLater();
|
keba->deleteLater();
|
||||||
return info->finish(Thing::ThingErrorHardwareNotAvailable, QT_TR_NOOP("Error opening network port."));
|
return info->finish(Thing::ThingErrorHardwareNotAvailable, QT_TR_NOOP("Error opening network port."));
|
||||||
}
|
}
|
||||||
@ -154,6 +168,11 @@ void IntegrationPluginKeba::setupThing(ThingSetupInfo *info)
|
|||||||
void IntegrationPluginKeba::postSetupThing(Thing *thing)
|
void IntegrationPluginKeba::postSetupThing(Thing *thing)
|
||||||
{
|
{
|
||||||
qCDebug(dcKebaKeContact()) << "Post setup" << thing->name();
|
qCDebug(dcKebaKeContact()) << "Post setup" << thing->name();
|
||||||
|
if (thing->thingClassId() != wallboxThingClassId) {
|
||||||
|
qCWarning(dcKebaKeContact()) << "Thing class id not supported" << thing->thingClassId();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
KeContact *keba = m_kebaDevices.value(thing->id());
|
KeContact *keba = m_kebaDevices.value(thing->id());
|
||||||
if (!keba) {
|
if (!keba) {
|
||||||
qCWarning(dcKebaKeContact()) << "No Keba connection found for this thing";
|
qCWarning(dcKebaKeContact()) << "No Keba connection found for this thing";
|
||||||
@ -161,6 +180,9 @@ void IntegrationPluginKeba::postSetupThing(Thing *thing)
|
|||||||
keba->getReport2();
|
keba->getReport2();
|
||||||
keba->getReport3();
|
keba->getReport3();
|
||||||
}
|
}
|
||||||
|
if (thing->paramValue(wallboxThingMacAddressParamTypeId).toString().isEmpty()) {
|
||||||
|
m_discovery->discoverHosts(25);
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_updateTimer) {
|
if (!m_updateTimer) {
|
||||||
m_updateTimer = hardwareManager()->pluginTimerManager()->registerTimer(60);
|
m_updateTimer = hardwareManager()->pluginTimerManager()->registerTimer(60);
|
||||||
@ -173,17 +195,8 @@ void IntegrationPluginKeba::postSetupThing(Thing *thing)
|
|||||||
}
|
}
|
||||||
keba->getReport2();
|
keba->getReport2();
|
||||||
keba->getReport3();
|
keba->getReport3();
|
||||||
|
if (thing->stateValue(wallboxActivityStateTypeId).toString() == "Charging") {
|
||||||
if (m_chargingSessionStartTime.contains(thing->id())) {
|
keba->getReport1XX(100);
|
||||||
QDateTime startTime = m_chargingSessionStartTime.value(thing->id());
|
|
||||||
|
|
||||||
QTimeZone tz = QTimeZone(QTimeZone::systemTimeZoneId());
|
|
||||||
QDateTime currentTime = QDateTime::currentDateTime().toTimeZone(tz);
|
|
||||||
|
|
||||||
int minutes = (currentTime.toMSecsSinceEpoch() - startTime.toMSecsSinceEpoch())/60000;
|
|
||||||
thing->setStateValue(wallboxSessionTimeStateTypeId, minutes);
|
|
||||||
} else {
|
|
||||||
thing->setStateValue(wallboxSessionTimeStateTypeId, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -241,16 +254,6 @@ void IntegrationPluginKeba::setDeviceState(Thing *thing, KeContact::State state)
|
|||||||
thing->setStateValue(wallboxActivityStateTypeId, "Authorization rejected");
|
thing->setStateValue(wallboxActivityStateTypeId, "Authorization rejected");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state == KeContact::StateCharging) {
|
|
||||||
//Set charging session
|
|
||||||
QTimeZone tz = QTimeZone(QTimeZone::systemTimeZoneId());
|
|
||||||
QDateTime startedChargingSession = QDateTime::currentDateTime().toTimeZone(tz);
|
|
||||||
m_chargingSessionStartTime.insert(thing->id(), startedChargingSession);
|
|
||||||
} else {
|
|
||||||
m_chargingSessionStartTime.remove(thing->id());
|
|
||||||
thing->setStateValue(wallboxSessionTimeStateTypeId, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntegrationPluginKeba::setDevicePlugState(Thing *thing, KeContact::PlugState plugState)
|
void IntegrationPluginKeba::setDevicePlugState(Thing *thing, KeContact::PlugState plugState)
|
||||||
@ -403,7 +406,7 @@ void IntegrationPluginKeba::onReport1XXReceived(int reportNumber, const KeContac
|
|||||||
qCDebug(dcKebaKeContact()) << " - Session Id" << report.sessionId;
|
qCDebug(dcKebaKeContact()) << " - Session Id" << report.sessionId;
|
||||||
qCDebug(dcKebaKeContact()) << " - Curr HW" << report.currHW;
|
qCDebug(dcKebaKeContact()) << " - Curr HW" << report.currHW;
|
||||||
qCDebug(dcKebaKeContact()) << " - Energy start" << report.startEnergy;
|
qCDebug(dcKebaKeContact()) << " - Energy start" << report.startEnergy;
|
||||||
qCDebug(dcKebaKeContact()) << " - Energy present" << report.ePres;
|
qCDebug(dcKebaKeContact()) << " - Energy present" << report.presentEnergy;
|
||||||
qCDebug(dcKebaKeContact()) << " - Start time" << report.startTime;
|
qCDebug(dcKebaKeContact()) << " - Start time" << report.startTime;
|
||||||
qCDebug(dcKebaKeContact()) << " - End time" << report.endTime;
|
qCDebug(dcKebaKeContact()) << " - End time" << report.endTime;
|
||||||
qCDebug(dcKebaKeContact()) << " - Stop reason" << report.stopReason;
|
qCDebug(dcKebaKeContact()) << " - Stop reason" << report.stopReason;
|
||||||
@ -412,18 +415,32 @@ void IntegrationPluginKeba::onReport1XXReceived(int reportNumber, const KeContac
|
|||||||
qCDebug(dcKebaKeContact()) << " - Serial number" << report.serialNumber;
|
qCDebug(dcKebaKeContact()) << " - Serial number" << report.serialNumber;
|
||||||
qCDebug(dcKebaKeContact()) << " - Uptime" << report.seconds;
|
qCDebug(dcKebaKeContact()) << " - Uptime" << report.seconds;
|
||||||
|
|
||||||
// Report 101 is the lastest finished session
|
if (reportNumber == 100) {
|
||||||
if (reportNumber == 101) {
|
// Report 100 is the current charging session
|
||||||
|
if (report.endTime == 0) {
|
||||||
|
// if the charing session is finished the end time will be set
|
||||||
|
double duration = (report.seconds - report.startTime)/60.00;
|
||||||
|
thing->setStateValue(wallboxSessionTimeStateTypeId, duration);
|
||||||
|
} else {
|
||||||
|
// Charging session is finished and copied to Report 101
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (reportNumber == 101) {
|
||||||
|
// Report 101 is the lastest finished session
|
||||||
if (report.serialNumber == thing->stateValue(wallboxSerialnumberStateTypeId).toString()) {
|
if (report.serialNumber == thing->stateValue(wallboxSerialnumberStateTypeId).toString()) {
|
||||||
if (!m_lastSessionId.contains(thing->id())) {
|
if (!m_lastSessionId.contains(thing->id())) {
|
||||||
|
// This happens after reboot
|
||||||
m_lastSessionId.insert(thing->id(), report.sessionId);
|
m_lastSessionId.insert(thing->id(), report.sessionId);
|
||||||
} else {
|
} else {
|
||||||
if (m_lastSessionId.value(thing->id()) != report.sessionId) {
|
if (m_lastSessionId.value(thing->id()) != report.sessionId) {
|
||||||
qCDebug(dcKebaKeContact()) << "New session id receivd";
|
qCDebug(dcKebaKeContact()) << "New session id receivd";
|
||||||
Event event;
|
Event event;
|
||||||
|
event.setEventTypeId(wallboxChargingSessionFinishedEventTypeId);
|
||||||
event.setThingId(thing->id());
|
event.setThingId(thing->id());
|
||||||
ParamList params;
|
ParamList params;
|
||||||
//params << Param(wallboxSessio);
|
params << Param(wallboxChargingSessionFinishedEventEnergyParamTypeId, report.presentEnergy);
|
||||||
|
params << Param(wallboxChargingSessionFinishedEventDurationParamTypeId, report.endTime);
|
||||||
|
params << Param(wallboxChargingSessionFinishedEventIdParamTypeId);
|
||||||
event.setParams(params);
|
event.setParams(params);
|
||||||
emitEvent(event);
|
emitEvent(event);
|
||||||
}
|
}
|
||||||
@ -443,14 +460,17 @@ void IntegrationPluginKeba::onBroadcastReceived(KeContact::BroadcastType type, c
|
|||||||
if (!thing)
|
if (!thing)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
qCDebug(dcKebaKeContact()) << "Broadcast received" << type << "value" << content;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case KeContact::BroadcastTypePlug:
|
case KeContact::BroadcastTypePlug:
|
||||||
setDevicePlugState(thing, KeContact::PlugState(content.toInt()));
|
setDevicePlugState(thing, KeContact::PlugState(content.toInt()));
|
||||||
break;
|
break;
|
||||||
case KeContact::BroadcastTypeInput:
|
case KeContact::BroadcastTypeInput:
|
||||||
|
thing->setStateValue(wallboxInputStateTypeId, (content.toInt() == 1));
|
||||||
break;
|
break;
|
||||||
case KeContact::BroadcastTypeEPres:
|
case KeContact::BroadcastTypeEPres:
|
||||||
thing->setStateValue(wallboxSessionEnergyStateTypeId, content.toInt());
|
thing->setStateValue(wallboxSessionEnergyStateTypeId, content.toInt()/10000.00);
|
||||||
break;
|
break;
|
||||||
case KeContact::BroadcastTypeState:
|
case KeContact::BroadcastTypeState:
|
||||||
setDeviceState(thing, KeContact::State(content.toInt()));
|
setDeviceState(thing, KeContact::State(content.toInt()));
|
||||||
@ -459,6 +479,7 @@ void IntegrationPluginKeba::onBroadcastReceived(KeContact::BroadcastType type, c
|
|||||||
thing->setStateValue(wallboxMaxChargingCurrentStateTypeId, content.toInt());
|
thing->setStateValue(wallboxMaxChargingCurrentStateTypeId, content.toInt());
|
||||||
break;
|
break;
|
||||||
case KeContact::BroadcastTypeEnableSys:
|
case KeContact::BroadcastTypeEnableSys:
|
||||||
|
qCDebug(dcKebaKeContact()) << "Broadcast enable sys not implemented";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -491,6 +512,10 @@ void IntegrationPluginKeba::executeAction(ThingActionInfo *info)
|
|||||||
m_asyncActions.insert(requestId, info);
|
m_asyncActions.insert(requestId, info);
|
||||||
connect(info, &ThingActionInfo::aborted, this, [requestId, this]{m_asyncActions.remove(requestId);});
|
connect(info, &ThingActionInfo::aborted, this, [requestId, this]{m_asyncActions.remove(requestId);});
|
||||||
|
|
||||||
|
} else if(action.actionTypeId() == wallboxOutputX2ActionTypeId){
|
||||||
|
|
||||||
|
} else if(action.actionTypeId() == wallboxFailsafeModeActionTypeId){
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
qCWarning(dcKebaKeContact()) << "Unhandled ActionTypeId:" << action.actionTypeId();
|
qCWarning(dcKebaKeContact()) << "Unhandled ActionTypeId:" << action.actionTypeId();
|
||||||
info->finish(Thing::ThingErrorActionTypeNotFound);
|
info->finish(Thing::ThingErrorActionTypeNotFound);
|
||||||
|
|||||||
@ -41,6 +41,7 @@
|
|||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QUdpSocket>
|
#include <QUdpSocket>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
#include <QUdpSocket>
|
||||||
|
|
||||||
class IntegrationPluginKeba : public IntegrationPlugin
|
class IntegrationPluginKeba : public IntegrationPlugin
|
||||||
{
|
{
|
||||||
@ -65,13 +66,13 @@ private:
|
|||||||
PluginTimer *m_updateTimer = nullptr;
|
PluginTimer *m_updateTimer = nullptr;
|
||||||
PluginTimer *m_reconnectTimer = nullptr;
|
PluginTimer *m_reconnectTimer = nullptr;
|
||||||
|
|
||||||
|
QUdpSocket *m_udpSocket = nullptr;
|
||||||
|
|
||||||
Discovery *m_discovery = nullptr;
|
Discovery *m_discovery = nullptr;
|
||||||
QHash<ThingId, KeContact *> m_kebaDevices;
|
QHash<ThingId, KeContact *> m_kebaDevices;
|
||||||
QHash<ThingId, int> m_lastSessionId;
|
QHash<ThingId, int> m_lastSessionId;
|
||||||
|
|
||||||
QHash<KeContact *, ThingSetupInfo *> m_asyncSetup;
|
|
||||||
QHash<QUuid, ThingActionInfo *> m_asyncActions;
|
QHash<QUuid, ThingActionInfo *> m_asyncActions;
|
||||||
QHash<ThingId, QDateTime> m_chargingSessionStartTime;
|
|
||||||
|
|
||||||
void setDeviceState(Thing *device, KeContact::State state);
|
void setDeviceState(Thing *device, KeContact::State state);
|
||||||
void setDevicePlugState(Thing *device, KeContact::PlugState plugState);
|
void setDevicePlugState(Thing *device, KeContact::PlugState plugState);
|
||||||
|
|||||||
@ -65,13 +65,7 @@
|
|||||||
"displayName": "Model",
|
"displayName": "Model",
|
||||||
"displayNameEvent": "Model changed",
|
"displayNameEvent": "Model changed",
|
||||||
"type": "QString",
|
"type": "QString",
|
||||||
"defaultValue": "Unknown",
|
"defaultValue": "Unknown"
|
||||||
"possibleValues": [
|
|
||||||
"Unknown",
|
|
||||||
"Keba P20",
|
|
||||||
"Keba P30",
|
|
||||||
"BMW"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "e941ace5-fb7f-4dc2-b3f2-188233f4e934",
|
"id": "e941ace5-fb7f-4dc2-b3f2-188233f4e934",
|
||||||
@ -107,6 +101,14 @@
|
|||||||
"writable": true,
|
"writable": true,
|
||||||
"defaultValue": false
|
"defaultValue": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "e5631593-f486-47cb-9951-b7597d0b769b",
|
||||||
|
"name": "systemEnabled",
|
||||||
|
"displayName": "System enabled",
|
||||||
|
"displayNameEvent": "System enabled changed",
|
||||||
|
"type": "bool",
|
||||||
|
"defaultValue": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "539e5602-6dd9-465d-9705-3bb59bcf8982",
|
"id": "539e5602-6dd9-465d-9705-3bb59bcf8982",
|
||||||
"name": "activity",
|
"name": "activity",
|
||||||
@ -216,7 +218,7 @@
|
|||||||
"displayName": "Power consumption",
|
"displayName": "Power consumption",
|
||||||
"displayNameEvent": "Power consumtion changed",
|
"displayNameEvent": "Power consumtion changed",
|
||||||
"type": "double",
|
"type": "double",
|
||||||
"unit": "Watt",
|
"unit": "KiloWatt",
|
||||||
"defaultValue": 0
|
"defaultValue": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -281,6 +283,16 @@
|
|||||||
"type": "int",
|
"type": "int",
|
||||||
"unit": "Seconds",
|
"unit": "Seconds",
|
||||||
"defaultValue": 0
|
"defaultValue": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "f1758c5c-2c02-41cb-93ec-b778a3c78d28",
|
||||||
|
"name": "failsafeMode",
|
||||||
|
"displayName": "Failsafe mode",
|
||||||
|
"displayNameEvent": "Failsafe mode changed",
|
||||||
|
"displayNameAction": "Set failsafe mode",
|
||||||
|
"writable": true,
|
||||||
|
"type": "bool",
|
||||||
|
"defaultValue": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"actionTypes": [
|
"actionTypes": [
|
||||||
|
|||||||
@ -34,8 +34,9 @@
|
|||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
|
|
||||||
|
|
||||||
KeContact::KeContact(QHostAddress address, QObject *parent) :
|
KeContact::KeContact(const QHostAddress &address, QUdpSocket *udpSocket, QObject *parent) :
|
||||||
QObject(parent),
|
QObject(parent),
|
||||||
|
m_udpSocket(udpSocket),
|
||||||
m_address(address)
|
m_address(address)
|
||||||
{
|
{
|
||||||
m_requestTimeoutTimer = new QTimer(this);
|
m_requestTimeoutTimer = new QTimer(this);
|
||||||
@ -54,15 +55,16 @@ KeContact::~KeContact() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool KeContact::init(){
|
bool KeContact::init(){
|
||||||
|
qCDebug(dcKebaKeContact()) << "Initializing Keba connection";
|
||||||
if(!m_udpSocket){
|
if(m_udpSocket){
|
||||||
m_udpSocket = new QUdpSocket(this);
|
connect(m_udpSocket, &QUdpSocket::readyRead, this, &KeContact::readPendingDatagrams);
|
||||||
if (!m_udpSocket->bind(QHostAddress::AnyIPv4, 7090, QAbstractSocket::ShareAddress)) {
|
if (!m_udpSocket->bind(QHostAddress::AnyIPv4, m_port, QAbstractSocket::ShareAddress)) {
|
||||||
qCWarning(dcKebaKeContact()) << "Cannot bind to port" << 7090;
|
qCWarning(dcKebaKeContact()) << "Cannot bind to port" << m_port;
|
||||||
delete m_udpSocket;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
connect(m_udpSocket, &QUdpSocket::readyRead, this, &KeContact::readPendingDatagrams);
|
} else {
|
||||||
|
qCWarning(dcKebaKeContact()) << "UDP socket not valid";
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -94,6 +96,7 @@ QUuid KeContact::stop(const QByteArray &rfidToken)
|
|||||||
|
|
||||||
void KeContact::setAddress(const QHostAddress &address)
|
void KeContact::setAddress(const QHostAddress &address)
|
||||||
{
|
{
|
||||||
|
qCDebug(dcKebaKeContact()) << "Updating Keba connection address" << address.toString();
|
||||||
m_address = address;
|
m_address = address;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,7 +126,7 @@ void KeContact::sendCommand(const QByteArray &command)
|
|||||||
m_commandList.append(command);
|
m_commandList.append(command);
|
||||||
} else {
|
} else {
|
||||||
//send command
|
//send command
|
||||||
m_udpSocket->writeDatagram(command, m_address, 7090);
|
m_udpSocket->writeDatagram(command, m_address, m_port);
|
||||||
m_requestTimeoutTimer->start(5000);
|
m_requestTimeoutTimer->start(5000);
|
||||||
m_deviceBlocked = true;
|
m_deviceBlocked = true;
|
||||||
}
|
}
|
||||||
@ -142,7 +145,7 @@ void KeContact::handleNextCommandInQueue()
|
|||||||
qCDebug(dcKebaKeContact()) << "Handle Command Queue- Pending commands" << m_commandList.length() << "Pending requestIds" << m_pendingRequests.length();
|
qCDebug(dcKebaKeContact()) << "Handle Command Queue- Pending commands" << m_commandList.length() << "Pending requestIds" << m_pendingRequests.length();
|
||||||
if (!m_commandList.isEmpty()) {
|
if (!m_commandList.isEmpty()) {
|
||||||
QByteArray command = m_commandList.takeFirst();
|
QByteArray command = m_commandList.takeFirst();
|
||||||
m_udpSocket->writeDatagram(command, m_address, 7090);
|
m_udpSocket->writeDatagram(command, m_address, m_port);
|
||||||
m_requestTimeoutTimer->start(5000);
|
m_requestTimeoutTimer->start(5000);
|
||||||
} else {
|
} else {
|
||||||
//nothing to do
|
//nothing to do
|
||||||
@ -161,7 +164,7 @@ QUuid KeContact::enableOutput(bool state)
|
|||||||
} else{
|
} else{
|
||||||
datagram.append("ena 0");
|
datagram.append("ena 0");
|
||||||
}
|
}
|
||||||
qCDebug(dcKebaKeContact()) << "Datagram : " << datagram;
|
qCDebug(dcKebaKeContact()) << "Enable output, command:" << datagram;
|
||||||
sendCommand(datagram, requestId);
|
sendCommand(datagram, requestId);
|
||||||
return requestId;
|
return requestId;
|
||||||
}
|
}
|
||||||
@ -174,7 +177,7 @@ QUuid KeContact::setMaxAmpere(int milliAmpere)
|
|||||||
qCDebug(dcKebaKeContact()) << "Update max current to : " << milliAmpere;
|
qCDebug(dcKebaKeContact()) << "Update max current to : " << milliAmpere;
|
||||||
QByteArray data;
|
QByteArray data;
|
||||||
data.append("curr " + QVariant(milliAmpere).toByteArray());
|
data.append("curr " + QVariant(milliAmpere).toByteArray());
|
||||||
qCDebug(dcKebaKeContact()) << "sSnd command: " << data;
|
qCDebug(dcKebaKeContact()) << "Set max. ampere, command: " << data;
|
||||||
sendCommand(data, requestId);
|
sendCommand(data, requestId);
|
||||||
return requestId;
|
return requestId;
|
||||||
}
|
}
|
||||||
@ -196,7 +199,7 @@ QUuid KeContact::displayMessage(const QByteArray &message)
|
|||||||
modifiedMessage.resize(23);
|
modifiedMessage.resize(23);
|
||||||
}
|
}
|
||||||
data.append("display 0 0 0 0 " + modifiedMessage);
|
data.append("display 0 0 0 0 " + modifiedMessage);
|
||||||
qCDebug(dcKebaKeContact()) << "Send command: " << data;
|
qCDebug(dcKebaKeContact()) << "Display message, command: " << data;
|
||||||
sendCommand(data, requestId);
|
sendCommand(data, requestId);
|
||||||
return requestId;
|
return requestId;
|
||||||
}
|
}
|
||||||
@ -208,7 +211,7 @@ QUuid KeContact::chargeWithEnergyLimit(double energy)
|
|||||||
|
|
||||||
QByteArray data;
|
QByteArray data;
|
||||||
data.append("setenergy " + QVariant(static_cast<int>(energy*10000)).toByteArray());
|
data.append("setenergy " + QVariant(static_cast<int>(energy*10000)).toByteArray());
|
||||||
qCDebug(dcKebaKeContact()) << "Send command: " << data;
|
qCDebug(dcKebaKeContact()) << "Charge with energy limit, command: " << data;
|
||||||
sendCommand(data, requestId);
|
sendCommand(data, requestId);
|
||||||
return requestId;
|
return requestId;
|
||||||
}
|
}
|
||||||
@ -223,7 +226,7 @@ QUuid KeContact::setFailsafe(int timeout, int current, bool save)
|
|||||||
data.append(" "+QVariant(timeout).toByteArray());
|
data.append(" "+QVariant(timeout).toByteArray());
|
||||||
data.append(" "+QVariant(current).toByteArray());
|
data.append(" "+QVariant(current).toByteArray());
|
||||||
data.append((save ? " 1":" 0"));
|
data.append((save ? " 1":" 0"));
|
||||||
qCDebug(dcKebaKeContact()) << "Send command: " << data;
|
qCDebug(dcKebaKeContact()) << "Set failsafe mode, command: " << data;
|
||||||
sendCommand(data, requestId);
|
sendCommand(data, requestId);
|
||||||
return requestId;
|
return requestId;
|
||||||
}
|
}
|
||||||
@ -233,31 +236,35 @@ void KeContact::getDeviceInformation()
|
|||||||
{
|
{
|
||||||
QByteArray data;
|
QByteArray data;
|
||||||
data.append("i");
|
data.append("i");
|
||||||
qCDebug(dcKebaKeContact()) << "send command: " << data;
|
qCDebug(dcKebaKeContact()) << "Get device information, command: " << data;
|
||||||
sendCommand(data);
|
sendCommand(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeContact::getReport1()
|
void KeContact::getReport1()
|
||||||
{
|
{
|
||||||
QByteArray data;
|
getReport(1);
|
||||||
data.append("report 1");
|
|
||||||
qCDebug(dcKebaKeContact()) << "send command : " << data;
|
|
||||||
sendCommand(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeContact::getReport2()
|
void KeContact::getReport2()
|
||||||
{
|
{
|
||||||
QByteArray data;
|
getReport(2);
|
||||||
data.append("report 2");
|
|
||||||
qCDebug(dcKebaKeContact()) << "send command: " << data;
|
|
||||||
sendCommand(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeContact::getReport3()
|
void KeContact::getReport3()
|
||||||
|
{
|
||||||
|
getReport(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeContact::getReport1XX(int reportNumber)
|
||||||
|
{
|
||||||
|
getReport(reportNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeContact::getReport(int reportNumber)
|
||||||
{
|
{
|
||||||
QByteArray data;
|
QByteArray data;
|
||||||
data.append("report 3");
|
data.append("report "+QVariant(reportNumber).toByteArray());
|
||||||
qCDebug(dcKebaKeContact()) << "data: " << data;
|
qCDebug(dcKebaKeContact()) << "Get report" << reportNumber << "Command:" << data;
|
||||||
sendCommand(data);
|
sendCommand(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,7 +274,7 @@ QUuid KeContact::unlockCharger()
|
|||||||
m_pendingRequests.append(requestId);
|
m_pendingRequests.append(requestId);
|
||||||
QByteArray data;
|
QByteArray data;
|
||||||
data.append("unlock");
|
data.append("unlock");
|
||||||
qCDebug(dcKebaKeContact()) << "send command: " << data;
|
qCDebug(dcKebaKeContact()) << "Unlock charger, command: " << data;
|
||||||
sendCommand(data);
|
sendCommand(data);
|
||||||
return requestId;
|
return requestId;
|
||||||
}
|
}
|
||||||
@ -281,18 +288,21 @@ void KeContact::readPendingDatagrams()
|
|||||||
quint16 senderPort;
|
quint16 senderPort;
|
||||||
|
|
||||||
while (socket->hasPendingDatagrams()) {
|
while (socket->hasPendingDatagrams()) {
|
||||||
datagram.resize(socket->pendingDatagramSize());
|
|
||||||
socket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
|
|
||||||
if (sender != m_address) {
|
if (sender != m_address) {
|
||||||
//Only process data from the target device
|
//Only process data from the target device
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
datagram.resize(socket->pendingDatagramSize());
|
||||||
|
socket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
|
||||||
|
qCDebug(dcKebaKeContact()) << "Data received" << datagram;
|
||||||
|
|
||||||
if (m_reachable != true) {
|
if (m_reachable != true) {
|
||||||
m_reachable = true;
|
m_reachable = true;
|
||||||
emit reachableChanged(true);
|
emit reachableChanged(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(dcKebaKeContact()) << "Data received" << datagram;
|
|
||||||
if(datagram.contains("TCH-OK")){
|
if(datagram.contains("TCH-OK")){
|
||||||
|
|
||||||
//Command response has been received, now send the next command
|
//Command response has been received, now send the next command
|
||||||
@ -399,14 +409,19 @@ void KeContact::readPendingDatagrams()
|
|||||||
reportThree.seconds = data.value("Sec").toInt();
|
reportThree.seconds = data.value("Sec").toInt();
|
||||||
emit reportThreeReceived(reportThree);
|
emit reportThreeReceived(reportThree);
|
||||||
} else if (id >= 100) {
|
} else if (id >= 100) {
|
||||||
|
|
||||||
Report1XX report;
|
Report1XX report;
|
||||||
report.sessionId = data.value("Session ID").toInt();
|
report.sessionId = data.value("Session ID").toInt();
|
||||||
report.currHW = data.value("Curr HW").toInt();
|
report.currHW = data.value("Curr HW").toInt();
|
||||||
//report. = data.value("Curr HW").toInt(); TODO
|
report.startTime = data.value("E Start ").toInt()/10000.00;
|
||||||
report.currHW = data.value("Curr HW").toInt();
|
report.presentEnergy = data.value("E Pres ").toInt()/10000.00;
|
||||||
report.currHW = data.value("Curr HW").toInt();
|
report.startTime = data.value("started[s]").toInt();
|
||||||
report.currHW = data.value("Curr HW").toInt();
|
report.endTime = data.value("ended[s] ").toInt();
|
||||||
report.currHW = data.value("Curr HW").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);
|
emit report1XXReceived(id, report);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -42,18 +42,10 @@ class KeContact : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit KeContact(QHostAddress address, QObject *parent = nullptr);
|
explicit KeContact(const QHostAddress &address, QUdpSocket *udpSocket, QObject *parent = nullptr);
|
||||||
~KeContact();
|
~KeContact();
|
||||||
bool init();
|
bool init();
|
||||||
|
|
||||||
enum Model {
|
|
||||||
ModelUnkown,
|
|
||||||
ModelP20,
|
|
||||||
ModelP30,
|
|
||||||
ModelBMW
|
|
||||||
};
|
|
||||||
Q_ENUM(Model)
|
|
||||||
|
|
||||||
enum State {
|
enum State {
|
||||||
StateStarting = 0,
|
StateStarting = 0,
|
||||||
StateNotReady,
|
StateNotReady,
|
||||||
@ -81,6 +73,7 @@ public:
|
|||||||
BroadcastTypeMaxCurr,
|
BroadcastTypeMaxCurr,
|
||||||
BroadcastTypeEPres
|
BroadcastTypeEPres
|
||||||
};
|
};
|
||||||
|
Q_ENUM(BroadcastType)
|
||||||
|
|
||||||
struct ReportOne {
|
struct ReportOne {
|
||||||
QString product; // Model name (variant
|
QString product; // Model name (variant
|
||||||
@ -131,7 +124,7 @@ public:
|
|||||||
int sessionId; // running session counter; not resettable"
|
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
|
int currHW; // maximum charging current of the cable and the charging station setting (equal to report 2)"E
|
||||||
double startEnergy; // total energy value at the beginning of the session"
|
double startEnergy; // total energy value at the beginning of the session"
|
||||||
double ePres; // delivered energy until now (equal to E pres in report 3)"
|
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; NTP implementation is still under progress)"
|
||||||
int endTime; // system time when the session has ended"
|
int endTime; // system time when the session has ended"
|
||||||
int stopReason; // reason for stopping the session (1 = vehicle unplug; 10 = Rfid token)"
|
int stopReason; // reason for stopping the session (1 = vehicle unplug; 10 = Rfid token)"
|
||||||
@ -160,16 +153,13 @@ public:
|
|||||||
void getReport1(); // Command “report”
|
void getReport1(); // Command “report”
|
||||||
void getReport2();
|
void getReport2();
|
||||||
void getReport3();
|
void getReport3();
|
||||||
void getReport1XX(int reportNumber = 100);
|
void getReport1XX(int reportNumber = 100); // Command “report 1xx”
|
||||||
|
|
||||||
// Command “report 1xx”
|
|
||||||
|
|
||||||
// Command “currtime”
|
// Command “currtime”
|
||||||
// Command “output”
|
// Command “output”
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
int m_port = 7090;
|
||||||
bool m_reachable = false;
|
bool m_reachable = false;
|
||||||
QUdpSocket *m_udpSocket = nullptr;
|
QUdpSocket *m_udpSocket = nullptr;
|
||||||
QHostAddress m_address;
|
QHostAddress m_address;
|
||||||
@ -180,7 +170,7 @@ private:
|
|||||||
int m_serialNumber;
|
int m_serialNumber;
|
||||||
QList<QUuid> m_pendingRequests;
|
QList<QUuid> m_pendingRequests;
|
||||||
|
|
||||||
|
void getReport(int reportNumber);
|
||||||
void sendCommand(const QByteArray &data, const QUuid &requestId);
|
void sendCommand(const QByteArray &data, const QUuid &requestId);
|
||||||
void sendCommand(const QByteArray &data);
|
void sendCommand(const QByteArray &data);
|
||||||
void handleNextCommandInQueue();
|
void handleNextCommandInQueue();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user