EVerest: Add PCE EV11.4 charger

This commit is contained in:
Simon Stürz 2026-10-15 15:51:14 +02:00
parent 44158b8aec
commit ef2a7b7b42
6 changed files with 424 additions and 25 deletions

View File

@ -37,6 +37,16 @@
#include <nymeasettings.h>
#include <network/networkdevicediscovery.h>
static bool isRfidThingClass(const ThingClassId &thingClassId)
{
return thingClassId == everestChargerAcRfidThingClassId || thingClassId == everestChargerPceThingClassId;
}
static bool isAcThingClass(const ThingClassId &thingClassId)
{
return thingClassId == everestChargerAcThingClassId || isRfidThingClass(thingClassId);
}
IntegrationPluginEverest::IntegrationPluginEverest()
{
@ -50,8 +60,9 @@ void IntegrationPluginEverest::init()
Thing *target = rfidTarget();
if (!target)
return;
emit emitEvent(Event(everestChargerAcRfidTagDetectedEventTypeId, target->id(),
ParamList() << Param(everestChargerAcRfidTagDetectedEventCodeParamTypeId, code)));
const EventType eventType = target->thingClass().eventTypes().findByName("tagDetected");
emit emitEvent(Event(eventType.id(), target->id(),
ParamList() << Param(eventType.paramTypes().findByName("code").id(), code)));
});
m_rfidProvider->probe();
QFileInfo enableMqttFileInfo(NymeaSettings::settingsPath() + "/everest-mqtt");
@ -424,6 +435,13 @@ void IntegrationPluginEverest::setupThing(ThingSetupInfo *info)
if (available) {
thing->setStateValue(everestConnectionApiVersionStateTypeId, connection->client()->apiVersion());
const EverestJsonRpcClient::ChargerInfo chargerInfo = connection->client()->chargerInfo();
foreach (Thing *child, myThings().filterByParentId(thing->id()).filterByThingClassId(everestChargerPceThingClassId)) {
child->setStateValue(everestChargerPceFirmwareVersionStateTypeId, chargerInfo.firmwareVersion);
if (child->paramValue(everestChargerPceThingSerialNumberParamTypeId).toString() != chargerInfo.serialNumber)
child->setParamValue(everestChargerPceThingSerialNumberParamTypeId, chargerInfo.serialNumber);
}
// Finish the bounded provider probe before choosing a new child's class.
QPointer<Thing> guardedThing(thing);
QPointer<EverestConnection> guardedConnection(connection);
@ -479,6 +497,15 @@ void IntegrationPluginEverest::setupThing(ThingSetupInfo *info)
ThingDescriptor descriptor(everestChargerDcThingClassId, evseInfo.id, evseInfo.description, thing->id());
descriptor.setParams(ParamList() << Param(everestChargerDcThingIndexParamTypeId, evseInfo.index));
descriptors.append(descriptor);
} else if (withRfid && everestIsPceVendor(connection->client()->chargerInfo().vendor)) {
const EverestJsonRpcClient::ChargerInfo chargerInfo = connection->client()->chargerInfo();
const QString name = chargerInfo.model.isEmpty() ? evseInfo.id : chargerInfo.model;
qCDebug(dcEverest()) << "-> Adding new discovered PCE charger" << name << "on" << connection->client()->serverUrl();
ThingDescriptor descriptor(everestChargerPceThingClassId, name, evseInfo.description, thing->id());
descriptor.setParams(ParamList()
<< Param(everestChargerPceThingIndexParamTypeId, evseInfo.index)
<< Param(everestChargerPceThingSerialNumberParamTypeId, chargerInfo.serialNumber));
descriptors.append(descriptor);
} else {
// If not a DC charger, default to AC
qCDebug(dcEverest()) << "-> Adding new discovered AC charger on" << connection->client()->serverUrl();
@ -511,7 +538,7 @@ void IntegrationPluginEverest::setupThing(ThingSetupInfo *info)
connection->start();
return;
} else if (thing->thingClassId() == everestChargerAcThingClassId || thing->thingClassId() == everestChargerAcRfidThingClassId || thing->thingClassId() == everestChargerDcThingClassId) {
} else if (isAcThingClass(thing->thingClassId()) || thing->thingClassId() == everestChargerDcThingClassId) {
Thing *parentThing = myThings().findById(thing->parentId());
EverestConnection *connection = m_everstConnections.value(parentThing);
@ -520,6 +547,9 @@ void IntegrationPluginEverest::setupThing(ThingSetupInfo *info)
return;
}
if (thing->thingClassId() == everestChargerPceThingClassId && connection->available())
thing->setStateValue(everestChargerPceFirmwareVersionStateTypeId, connection->client()->chargerInfo().firmwareVersion);
info->finish(Thing::ThingErrorNoError);
connection->addThing(thing);
@ -530,17 +560,18 @@ void IntegrationPluginEverest::setupThing(ThingSetupInfo *info)
void IntegrationPluginEverest::executeAction(ThingActionInfo *info)
{
if (info->thing()->thingClassId() == everestChargerAcRfidThingClassId) {
const auto actionId = info->action().actionTypeId();
if (actionId == everestChargerAcRfidRfidEnrollmentActiveActionTypeId) {
if (isRfidThingClass(info->thing()->thingClassId())) {
ActionTypes actionTypes = info->thing()->thingClass().actionTypes();
const ActionType actionType = actionTypes.findById(info->action().actionTypeId());
if (actionType.name() == "rfidEnrollmentActive") {
info->thing()->setStateValue("rfidEnrollmentActive",
info->action().paramValue(everestChargerAcRfidRfidEnrollmentActiveActionRfidEnrollmentActiveParamTypeId));
info->action().paramValue(actionType.paramTypes().findByName("rfidEnrollmentActive").id()));
info->finish(Thing::ThingErrorNoError);
return;
}
if (actionId == everestChargerAcRfidTagAcceptedActionTypeId || actionId == everestChargerAcRfidTagRejectedActionTypeId) {
if (actionType.name() == "tagAccepted" || actionType.name() == "tagRejected") {
qCInfo(dcEverest()) << "RFID tag"
<< (actionId == everestChargerAcRfidTagAcceptedActionTypeId ? "accepted" : "rejected")
<< (actionType.name() == "tagAccepted" ? "accepted" : "rejected")
<< "for" << info->thing()->name() << "- charger feedback RPC is not yet available.";
info->thing()->setStateValue("rfidEnrollmentActive", false);
info->finish(Thing::ThingErrorNoError);
@ -598,7 +629,7 @@ void IntegrationPluginEverest::executeAction(ThingActionInfo *info)
}
return;
} else if (info->thing()->thingClassId() == everestChargerAcThingClassId || info->thing()->thingClassId() == everestChargerAcRfidThingClassId) {
} else if (isAcThingClass(info->thing()->thingClassId())) {
Thing *thing = info->thing();
Thing *parentThing = myThings().findById(thing->parentId());
EverestConnection *connection = m_everstConnections.value(parentThing);
@ -618,8 +649,13 @@ void IntegrationPluginEverest::executeAction(ThingActionInfo *info)
return;
}
if (info->action().actionTypeId() == everestChargerAcPowerActionTypeId || info->action().actionTypeId() == everestChargerAcRfidPowerActionTypeId) {
bool power = info->action().paramValue(thing->thingClassId() == everestChargerAcRfidThingClassId ? everestChargerAcRfidPowerActionPowerParamTypeId : everestChargerAcPowerActionPowerParamTypeId).toBool();
// Same action names across all AC thing classes, resolve by name
ActionTypes actionTypes = thing->thingClass().actionTypes();
const ActionType actionType = actionTypes.findById(info->action().actionTypeId());
const QVariant actionValue = info->action().paramValue(actionType.paramTypes().findByName(actionType.name()).id());
if (actionType.name() == "power") {
bool power = actionValue.toBool();
qCDebug(dcEverest()) << "Execute power action" << power;
EverestJsonRpcReply *reply = evse->setChargingAllowed(power) ;
connect(reply, &EverestJsonRpcReply::finished, reply, &EverestJsonRpcReply::deleteLater);
@ -641,8 +677,8 @@ void IntegrationPluginEverest::executeAction(ThingActionInfo *info)
info->thing()->setStateValue(QStringLiteral("power"), power);
info->finish(Thing::ThingErrorNoError);
});
} else if (info->action().actionTypeId() == everestChargerAcMaxChargingCurrentActionTypeId || info->action().actionTypeId() == everestChargerAcRfidMaxChargingCurrentActionTypeId) {
double current = info->action().paramValue(thing->thingClassId() == everestChargerAcRfidThingClassId ? everestChargerAcRfidMaxChargingCurrentActionMaxChargingCurrentParamTypeId : everestChargerAcMaxChargingCurrentActionMaxChargingCurrentParamTypeId).toDouble();
} else if (actionType.name() == "maxChargingCurrent") {
double current = actionValue.toDouble();
qCDebug(dcEverest()) << "Execute action set max charging current" << current << "[A]";
EverestJsonRpcReply *reply = evse->setACChargingCurrent(current) ;
connect(reply, &EverestJsonRpcReply::finished, reply, &EverestJsonRpcReply::deleteLater);
@ -664,8 +700,8 @@ void IntegrationPluginEverest::executeAction(ThingActionInfo *info)
info->thing()->setStateValue(QStringLiteral("maxChargingCurrent"), current);
info->finish(Thing::ThingErrorNoError);
});
} else if (info->action().actionTypeId() == everestChargerAcDesiredPhaseCountActionTypeId || info->action().actionTypeId() == everestChargerAcRfidDesiredPhaseCountActionTypeId) {
int phaseCount = info->action().paramValue(thing->thingClassId() == everestChargerAcRfidThingClassId ? everestChargerAcRfidDesiredPhaseCountActionDesiredPhaseCountParamTypeId : everestChargerAcDesiredPhaseCountActionDesiredPhaseCountParamTypeId).toInt();
} else if (actionType.name() == "desiredPhaseCount") {
int phaseCount = actionValue.toInt();
qCDebug(dcEverest()) << "Execute action set phase count" << phaseCount;
EverestJsonRpcReply *reply = evse->setACChargingPhaseCount(phaseCount);
connect(reply, &EverestJsonRpcReply::finished, reply, &EverestJsonRpcReply::deleteLater);
@ -786,7 +822,7 @@ void IntegrationPluginEverest::thingRemoved(Thing *thing)
}
} else if (thing->thingClassId() == everestConnectionThingClassId) {
m_everstConnections.take(thing)->deleteLater();
} else if (thing->thingClassId() == everestChargerAcThingClassId || thing->thingClassId() == everestChargerAcRfidThingClassId || thing->thingClassId() == everestChargerDcThingClassId) {
} else if (isAcThingClass(thing->thingClassId()) || thing->thingClassId() == everestChargerDcThingClassId) {
Thing *parentThing = myThings().findById(thing->parentId());
EverestConnection *connection = m_everstConnections.value(parentThing);
if (!connection)
@ -811,7 +847,7 @@ Thing *IntegrationPluginEverest::rfidTarget() const
if (!everestRfidEligible(connection->client()->serverUrl(), connection->client()->evseInfos()))
continue;
for (Thing *child : myThings().filterByParentId(it.key()->id())) {
if (child->thingClassId() != everestChargerAcRfidThingClassId
if (!isRfidThingClass(child->thingClassId())
|| child->paramValue("index").toInt() != connection->client()->evseInfos().first().index)
continue;
if (target)
@ -825,6 +861,8 @@ Thing *IntegrationPluginEverest::rfidTarget() const
void IntegrationPluginEverest::updateRfidAvailability()
{
Thing *target = rfidTarget();
for (Thing *thing : myThings().filterByThingClassId(everestChargerAcRfidThingClassId))
thing->setStateValue("rfidAvailable", thing == target && m_rfidProvider->ready());
for (Thing *thing : myThings()) {
if (isRfidThingClass(thing->thingClassId()))
thing->setStateValue("rfidAvailable", thing == target && m_rfidProvider->ready());
}
}

View File

@ -1048,7 +1048,335 @@
}
]
},
{
"name": "PcElectric",
"displayName": "PC Electric GmbH",
"id": "b365937b-f1d6-46bf-9ff1-e787373b8aa6",
"thingClasses": [
{
"name": "everestChargerPce",
"displayName": "EV11.4 Wallbox R37 11kW",
"id": "75453003-9005-4b82-aaa9-41e05426c64c",
"setupMethod": "JustAdd",
"createMethods": [
"auto"
],
"interfaces": [
"evchargerac",
"smartmeterconsumer",
"connectable",
"rfid"
],
"paramTypes": [
{
"id": "85db8ca5-b0cb-450d-89bd-4da9103da3f6",
"name": "index",
"displayName": "Index",
"type": "uint",
"defaultValue": 0
},
{
"id": "df601274-b5a9-4e4c-b390-601d51a64b75",
"name": "serialNumber",
"displayName": "Serial number",
"type": "QString",
"defaultValue": "",
"readOnly": true
}
],
"settingsTypes": [],
"stateTypes": [
{
"id": "7289ecfe-27e2-4e80-8b43-919226810b2e",
"name": "firmwareVersion",
"displayName": "Firmware version",
"type": "QString",
"defaultValue": ""
},
{
"id": "247b7178-d208-4457-8725-675aa9710b05",
"name": "connected",
"displayName": "Connected",
"type": "bool",
"cached": false,
"defaultValue": false
},
{
"id": "0cbf8be7-7937-4424-9628-7458f1684eec",
"name": "power",
"displayName": "Charging enabled",
"displayNameAction": "Enable or disable charging",
"type": "bool",
"defaultValue": false,
"writable": true
},
{
"id": "ed1e72fd-2e2b-41d8-8135-1d72b44e8acd",
"name": "maxChargingCurrent",
"displayName": "Maximum charging current",
"displayNameAction": "Set maximum charging current",
"type": "double",
"unit": "Ampere",
"defaultValue": 6,
"minValue": 6,
"maxValue": 32,
"stepSize": 0.01,
"writable": true
},
{
"id": "f71d4542-2d26-4ede-8dd1-4b1752f69dff",
"name": "pluggedIn",
"displayName": "Plugged in",
"type": "bool",
"defaultValue": false
},
{
"id": "37cdab39-d18d-4905-8e8e-20e07aa9a1a9",
"name": "charging",
"displayName": "Charging",
"type": "bool",
"defaultValue": false
},
{
"id": "db274123-6fbe-4a11-9db3-cbe9439a6dbe",
"name": "phaseCount",
"displayName": "Active phases",
"type": "uint",
"minValue": 1,
"maxValue": 3,
"defaultValue": 1
},
{
"id": "e1835179-1df1-480d-9d2a-528244f6bb0c",
"name": "desiredPhaseCount",
"displayName": "Desired phase count",
"displayNameAction": "Set desired phase count",
"type": "uint",
"minValue": 1,
"maxValue": 3,
"possibleValues": [
1,
3
],
"writable": true,
"defaultValue": 3
},
{
"id": "9d4be811-cb50-4828-856d-3dea56e2a2a5",
"name": "state",
"displayName": "State",
"type": "QString",
"defaultValue": "",
"cached": false
},
{
"id": "54c23843-03c2-4eb6-8374-bd383a2189e8",
"name": "totalEnergyConsumed",
"displayName": "Total energy",
"type": "double",
"unit": "KiloWattHour",
"defaultValue": 0,
"cached": true
},
{
"id": "11f62675-ce61-4e60-8104-5d0e20490982",
"name": "sessionEnergy",
"displayName": "Session energy",
"type": "double",
"unit": "KiloWattHour",
"defaultValue": 0,
"suggestLogging": true
},
{
"id": "38f27852-0153-4f68-be73-765e18bb39df",
"name": "currentPower",
"displayName": "Current power",
"type": "double",
"unit": "Watt",
"defaultValue": 0,
"cached": false
},
{
"id": "a77a5580-caa3-419d-ba2c-1035e85df0e4",
"name": "currentPowerPhaseA",
"displayName": "Current power phase A",
"displayNameEvent": "Current power phase A changed",
"type": "double",
"unit": "Watt",
"defaultValue": 0,
"cached": false
},
{
"id": "23876033-cf4d-48dc-8a99-4a8513f2808f",
"name": "currentPowerPhaseB",
"displayName": "Current power phase B",
"displayNameEvent": "Current power phase B changed",
"type": "double",
"unit": "Watt",
"defaultValue": 0,
"cached": false
},
{
"id": "7373304a-2d65-49b6-b551-9c047e823a2e",
"name": "currentPowerPhaseC",
"displayName": "Current power phase C",
"displayNameEvent": "Current power phase C changed",
"type": "double",
"unit": "Watt",
"defaultValue": 0,
"cached": false
},
{
"id": "bf1ad69c-2b9c-4600-a7b0-a915230732d3",
"name": "currentPhaseA",
"displayName": "Phase A current",
"displayNameEvent": "Phase A current changed",
"type": "double",
"unit": "Ampere",
"defaultValue": 0,
"cached": false
},
{
"id": "7d7ac0c9-5c75-4ba5-9b6b-417ea79c65d4",
"name": "currentPhaseB",
"displayName": "Phase B current",
"displayNameEvent": "Phase B current changed",
"type": "double",
"unit": "Ampere",
"defaultValue": 0,
"cached": false
},
{
"id": "7ed089e8-9634-45d5-a627-69f7c32440a5",
"name": "currentPhaseC",
"displayName": "Phase C current",
"displayNameEvent": "Phase C current changed",
"type": "double",
"unit": "Ampere",
"defaultValue": 0,
"cached": false
},
{
"id": "14d4c49f-3bc5-4e24-a4b9-219dc37cfe10",
"name": "voltagePhaseA",
"displayName": "Phase A voltage",
"displayNameEvent": "Phase A volatage changed",
"type": "double",
"unit": "Volt",
"defaultValue": 0,
"cached": false
},
{
"id": "3da9556e-285b-494d-aafa-6189b2fa81a4",
"name": "voltagePhaseB",
"displayName": "Phase B voltage",
"displayNameEvent": "Phase B voltage changed",
"type": "double",
"unit": "Volt",
"defaultValue": 0,
"cached": false
},
{
"id": "befca107-3f05-4fa2-9558-1ddcbd399844",
"name": "voltagePhaseC",
"displayName": "Phase C voltage",
"displayNameEvent": "Phase C voltage changed",
"type": "double",
"unit": "Volt",
"defaultValue": 0,
"cached": false
},
{
"id": "78f2f4c6-e8f5-4805-8392-3713aac56e8e",
"name": "temperature",
"displayName": "Temperature",
"type": "double",
"unit": "DegreeCelsius",
"defaultValue": 0,
"cached": false
},
{
"id": "50c41265-1b35-4d3a-99e2-42e55737d652",
"name": "fanSpeed",
"displayName": "Fan speed",
"type": "double",
"unit": "Rpm",
"defaultValue": 0,
"cached": false
},
{
"id": "00c7ac1a-f931-46ce-a8ec-3247781adc23",
"name": "rfidAvailable",
"displayName": "RFID reader available",
"type": "bool",
"cached": false,
"defaultValue": false
},
{
"id": "0bd96b5e-fec4-4ae4-81c2-17f23cb9a487",
"name": "authorizedUsername",
"displayName": "Authorized username",
"type": "QString",
"cached": false,
"defaultValue": ""
},
{
"id": "f3e0fc14-387c-49d3-9e8d-ad7b3d18fc29",
"name": "authorizedDisplayName",
"displayName": "Authorized display name",
"type": "QString",
"cached": false,
"defaultValue": ""
},
{
"id": "bd05d60a-1268-480f-aecd-b4c0ae37c513",
"name": "authorizedTagHash",
"displayName": "Authorized tag hash",
"type": "QString",
"cached": false,
"defaultValue": ""
},
{
"id": "9c2eb309-5bf0-48fb-b4e6-7315a02a9a39",
"name": "rfidEnrollmentActive",
"displayName": "RFID enrollment active",
"displayNameAction": "Set RFID enrollment mode",
"type": "bool",
"writable": true,
"cached": false,
"defaultValue": false
}
],
"actionTypes": [
{
"id": "bb0ef68a-8a63-4604-8bda-5eec2dcf75c1",
"name": "tagAccepted",
"displayName": "Accept RFID tag"
},
{
"id": "65a053b0-f40e-49ec-83c5-e6da8a2fdeb1",
"name": "tagRejected",
"displayName": "Reject RFID tag"
}
],
"eventTypes": [
{
"id": "d0666281-1526-4d3c-8cce-f5d701768013",
"name": "tagDetected",
"displayName": "RFID tag detected",
"paramTypes": [
{
"id": "942c39f5-858d-4e56-85d6-819d4186caf9",
"name": "code",
"displayName": "Tag code",
"type": "QString"
}
]
}
]
}
]
}
]
}

View File

@ -211,7 +211,7 @@ void EverestEvse::initialize()
void EverestEvse::processEvseStatus()
{
if ((m_thing->thingClassId() == everestChargerAcThingClassId || m_thing->thingClassId() == everestChargerAcRfidThingClassId)) {
if ((m_thing->thingClassId() == everestChargerAcThingClassId || m_thing->thingClassId() == everestChargerAcRfidThingClassId || m_thing->thingClassId() == everestChargerPceThingClassId)) {
m_thing->setStateValue(QStringLiteral("power"), m_evseStatus.chargingAllowed);
m_thing->setStateValue(QStringLiteral("sessionEnergy"), m_evseStatus.chargedEnergyWh / 1000.0);
m_thing->setStateValue(QStringLiteral("state"), m_evseStatus.evseStateString);
@ -248,7 +248,7 @@ void EverestEvse::processEvseStatus()
void EverestEvse::processHardwareCapabilities()
{
if ((m_thing->thingClassId() == everestChargerAcThingClassId || m_thing->thingClassId() == everestChargerAcRfidThingClassId)) {
if ((m_thing->thingClassId() == everestChargerAcThingClassId || m_thing->thingClassId() == everestChargerAcRfidThingClassId || m_thing->thingClassId() == everestChargerPceThingClassId)) {
if (!m_hardwareCapabilities.phaseSwitchDuringCharging) {
// Only option left is set the desired phase count to 3, force that value
m_thing->setStatePossibleValues(QStringLiteral("desiredPhaseCount"), { 3 });
@ -265,7 +265,7 @@ void EverestEvse::processHardwareCapabilities()
void EverestEvse::processMeterData()
{
if ((m_thing->thingClassId() == everestChargerAcThingClassId || m_thing->thingClassId() == everestChargerAcRfidThingClassId)) {
if ((m_thing->thingClassId() == everestChargerAcThingClassId || m_thing->thingClassId() == everestChargerAcRfidThingClassId || m_thing->thingClassId() == everestChargerPceThingClassId)) {
m_thing->setStateValue(QStringLiteral("currentPower"), m_meterData.powerTotal);

View File

@ -31,4 +31,9 @@ inline bool everestRfidEligible(const QUrl &url, const QList<EverestJsonRpcClien
return ac;
}
inline bool everestIsPceVendor(const QString &vendor)
{
return vendor.trimmed().compare(QStringLiteral("PCE"), Qt::CaseInsensitive) == 0;
}
#endif // EVERESTRFIDUTILS_H

View File

@ -54,7 +54,9 @@ public:
QVariantMap result;
const QString method = request.value("method").toString();
if (method == "API.Hello") {
result = {{"api_version", "1.0"}, {"everest_version", "test"}, {"authentication_required", false}, {"charger_info", QVariantMap()}};
result = {{"api_version", "1.0"}, {"everest_version", "test"}, {"authentication_required", false}, {"charger_info", QVariantMap{
{"vendor", "PCE"}, {"model", "EV11.4 Wallbox R37 11kW"},
{"serial", "1234567890"}, {"firmware_version", "0.10.9"}}}};
} else if (method == "ChargePoint.GetEVSEInfos") {
result = {{"error", "NoError"}, {"infos", QVariantList()}};
} else {
@ -102,6 +104,12 @@ private slots:
QTRY_VERIFY_WITH_TIMEOUT(connection.available(), 8000);
QCOMPARE(availableSpy.count(), 1);
QCOMPARE(availableSpy.first().first().toBool(), true);
const EverestJsonRpcClient::ChargerInfo chargerInfo = connection.client()->chargerInfo();
QCOMPARE(chargerInfo.vendor, QString("PCE"));
QCOMPARE(chargerInfo.model, QString("EV11.4 Wallbox R37 11kW"));
QCOMPARE(chargerInfo.serialNumber, QString("1234567890"));
QCOMPARE(chargerInfo.firmwareVersion, QString("0.10.9"));
}
void noReconnectWhenStopped()

View File

@ -145,6 +145,26 @@ private slots:
}
QCOMPARE(everestRfidEligible(QUrl(url), topology), eligible);
}
void pceVendor_data()
{
QTest::addColumn<QString>("vendor");
QTest::addColumn<bool>("pce");
QTest::newRow("upper") << "PCE" << true;
QTest::newRow("lower") << "pce" << true;
QTest::newRow("mixed-whitespace") << " Pce " << true;
QTest::newRow("prefix") << "PCEX" << false;
QTest::newRow("full-name") << "PC Electric Gesellschaft m.b.H." << false;
QTest::newRow("other") << "Chargebyte" << false;
QTest::newRow("empty") << "" << false;
}
void pceVendor()
{
QFETCH(QString, vendor);
QFETCH(bool, pce);
QCOMPARE(everestIsPceVendor(vendor), pce);
}
};
QTEST_GUILESS_MAIN(TestRfidProviderClient)
#include "tst_rfidproviderclient.moc"